在 Bash 中围绕一个除数

如何对两个除数的结果进行四舍五入,例如。

3/2

就像我一样

testOne=$((3/2))

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

179242 次浏览

要在截断算法中进行四舍五入,只需将 (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

Bash 不会给你3/2的正确结果,因为它不做浮点运算。你可以使用 awk 这样的工具

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

或者公元前

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

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

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

在我看来,用 awk 比较新潮。

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

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

逻辑是简单的,如果 var 十进制值小于。5那么最接近的值是整数值。如果十进制值大于.5,那么下一个整数值将被添加,因为 awk 只取整数部分。问题解决了

我想这些应该够了。

$ echo "3/2" | bc

如果正数的整数除法四舍五入为零,那么你可以向红利中加一个小于除数的数,使它四舍五入。

也就是说,用 (X + Y - 1) / Y代替 X / Y

证据:

  • 案例1: X = k * Y(X 是 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。这表明这种行为是集中的。如果我们有一个 0 < m < Y0,这是一个 0 < m < Y1倍的 0 < m < Y2,如果我们只加1到它,除法四舍五入到 k + 1

但是这个四舍五入是完全相反的,所有不精确的除法都从零开始,那么介于两者之间的除法呢?

这可以通过用 Y/2“启动”分子来实现。计算 (X+Y/2)/Y而不是 X/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 121,所有等于 6的值,模 12,如 18(到2)等等。round 5 12下降到 0

对于奇数,行为是正确的。没有一个精确的有理数是介于两个连续的倍数之间的。例如,对于 11的分母,我们有 5/11 < 5.5/11 (exact middle) < 6/11; 和 round 5 11四舍五入,而 round 6 11四舍五入。

如果小数点是逗号(例如: 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

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

如果有余数,那么等式的第二部分将加到 True。(True = 1; False = 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

跟踪对我很管用。

 #!/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