在Bash中舍入一个分开的数字

问题描述 投票:43回答:10

我如何从两个分开的数字中舍入结果,例如

3/2

就像我一样

testOne=$((3/2))

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

linux bash math shell rounding
10个回答
70
投票

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

0
投票

以下为我工作。

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

30
投票

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

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

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


25
投票

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

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

或者

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

8
投票

如果你有一个整数除数的正数向零舍入,那么你可以将一个小于除数的一个除数加到被除数上以使它向上舍入。

也就是说,用X / Y取代(X + Y - 1) / 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有效。这表明行为四舍五入。如果我们有一个X,它是kY倍数,如果我们只添加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

每当除数是一个偶数,正数,如果分子与该数字的一半相等,它就会向上舍入,如果它小于该值则向下舍入。

例如,round 6 12转到1,所有等于6,modulo 12的值,如18(转到2)等等。 round 5 12下到0

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


4
投票

要向上舍入,您可以使用模数。

如果有余数,则等式的第二部分将添加到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

4
投票

给定浮点值,我们可以使用printf简单地舍入它:

# round $1 to $2 decimal places
round() {
    printf "%.2f" "$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

2
投票

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

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

对我而言似乎比使用awk更少陈词滥调。


1
投票

我认为这应该足够了。

$ echo "3/2" | bc 

1
投票

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

$ 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
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.