繁体   English   中英

在 Bash 中舍入除数

[英]Round a divided number in Bash

我将如何从两个相除的数字中取整结果,例如

3/2

就像我做的那样

testOne=$((3/2))

$testOne 包含“1”,而它应该四舍五入为“2”作为 3/2=1.5 的答案

要在截断算术中进行四舍五入,只需将(denom-1)添加到分子。

示例,四舍五入:

N/2
M/5
K/16

示例,四舍五入:

(N+1)/2
(M+4)/5
(K+15)/16

要进行四舍五入,请将(denom/2)添加到分子(一半将向上取整):

(N+1)/2
(M+2)/5
(K+8)/16

好的解决方案是获得最近的整数是

var=2.5
echo $var | awk '{print int($1+0.5)}'

如果 var 十进制值小于 0.5,则逻辑很简单,则采用的最接近的值是整数值。 好吧,如果十进制值大于 0.5,则添加下一个整数值,因为 awk 只取整数部分。 问题已解决

bash 不会给你 3/2 的正确结果,因为它不做浮动 pt 数学。 你可以使用awk之类的工具

$ awk  'BEGIN { rounded = sprintf("%.0f", 3/2); print rounded }'
2

或公元前

$ printf "%.0f" $(echo "scale=2;3/2" | bc)
2

如果您有向零舍入的正数的整数除法,那么您可以在被除数上加上比除数少 1 以使其四舍五入。

也就是说,将X / Y替换为(X + Y - 1) / Y

证明:

  • 情况 1: X = k * Y (X 是X = k * Y整数倍):在这种情况下,我们有(k * Y + Y - 1) / Y ,分为(k * Y) / Y + (Y - 1) / Y (Y - 1)/Y部分四舍五入为零,我们剩下的商为k 这正是我们想要的:当输入可整除时,我们希望调整后的计算仍然产生正确的精确商。

  • 情况 2: X = k * Y + m ,其中0 < m < Y (X 不是 Y 的倍数)。 在这种情况下,我们有一个k * Y + m + Y - 1k * Y + Y + m - 1的分子,我们可以将除法写为(k * Y)/Y + Y/Y + (m - 1)/Y 由于0 < m < Y0 <= m - 1 < Y - 1 ,所以最后一项(m - 1)/Y变为零。 我们剩下(k * Y)/Y + Y/Y ,结果为k + 1 这表明该行为四舍五入。 如果我们有一个XYk Y ,如果我们只给它加 1,除法会向上k + 1整为k + 1

但这种四舍五入是极其相反的; 所有不精确的除法都从零开始。 介于两者之间怎么样?

这可以通过用Y/2 “启动”分子来实现。 而不是X/Y ,计算(X+Y/2)/Y 代替证明,让我们对这一点进行实证:

$ round()
> {
>   echo $((($1 + $2/2) / $2))
> }
$ round 4 10
0
$ round 5 10
1
$ round 6 10
1
$ round 9 10
1
$ round 10 10
1
$ round 14 10
1
$ round 15 10
2

当除数是偶数、正数时,如果分子等于该数的一半,则向上舍入,如果小于 1,则向下舍入。

例如, round 6 12等于1 ,所有等于6值也是如此,取模12 ,例如18 (等于 2)等等。 round 5 12下降到0

对于奇数,行为是正确的。 没有一个精确的有理数介于两个连续的倍数之间。 例如,当分母为11我们有5/11 < 5.5/11 (exact middle) < 6/11 round 5 11轮向下round 6 11 ,而round 6 11轮向上round 6 11

要四舍五入,您可以使用模数。

如果有余数,等式的第二部分将与 True 相加。 (真 = 1;假 = 0)

例如:3/2

answer=$(((3 / 2) + (3 % 2 > 0)))
echo $answer
2

例如:100 / 2

answer=$(((100 / 2) + (100 % 2 > 0)))
echo $answer
50

例如:100 / 3

answer=$(((100 / 3) + (100 % 3 > 0)))
echo $answer
34

给定一个浮点值,我们可以用printf对其进行四舍五入:

# round $1 to $2 decimal places
round() {
    printf "%.${2:-0}f" "$1"
}

然后,

# do some math, bc style
math() {
    echo "$*" | bc -l
}

$ echo "Pi, to five decimal places, is $(round $(math "4*a(1)") 5)"
Pi, to five decimal places, is 3.14159

或者,使用原始请求:

$ echo "3/2, rounded to the nearest integer, is $(round $(math "3/2") 0)"
3/2, rounded to the nearest integer, is 2

如果小数点分隔符是逗号(例如:LC_NUMERIC=fr_FR.UTF-8,请参见此处):

$ printf "%.0f" $(echo "scale=2;3/2" | bc) 
bash: printf: 1.50: nombre non valable
0

ghostdog74 解决方案需要替换:

$ printf "%.0f" $(echo "scale=2;3/2" | bc | sed 's/[.]/,/')
2

或者

$ printf "%.0f" $(echo "scale=2;3/2" | bc | tr '.' ',')
2

另一种解决方案是在 python 命令中进行除法。 例如:

$ numerator=90
$ denominator=7
$ python -c "print (round(${numerator}.0 / ${denominator}.0))"

对我来说似乎不如使用 awk 过时。

我认为这应该足够了。

$ echo "3/2" | bc 

以下为我工作。

 #!/bin/bash
function float() {
bc << EOF
num = $1;
base = num / 1;
if (((num - base) * 10) > 1 )
    base += 1;
print base;
EOF
echo ""
}

float 3.2

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM