在Bash中使用bc舍入数字

时间:2014-11-11 09:04:59

标签: linux bash bc

我想使用bc计算平均值,包括3位小数,四舍五入到最接近的位置。

例如:

  

3,3和5的平均值应该产生3.667

  

平均值为3,3和4应该产生3.333

我试过了:

echo "scale=3; $sum/$n+0.0005" | bc

但是scale的行为并不像我预期的那样。我该怎么做才能解决我的问题?

3 个答案:

答案 0 :(得分:5)

添加0.0005的技巧并不是一个坏主意。虽然,它并没有那么好的工作方式。 scale在内部使用bc执行某些操作(如分区)。

在您的情况下,最好先执行除法,可能会使用较大的scale-l切换到bc 1 (如果您的版本支持它),然后添加0.0005然后设置scale=3并在内部执行涉及scale的操作以执行截断。

类似的东西:

`a=$sum/$n+0.0005; scale=3; a/1`

当然,无论sum是正面还是负面,您都希望采用不同的方式。幸运的是,bc有一些条件运算符。

`a=$sum/$n; if(a>0) a+=0.0005 else if (a<0) a-=0.0005; scale=3; a/1`

然后,您希望使用printf格式化此答案。

包含在函数round中(您可以选择小数位数):

round() {
    # $1 is expression to round (should be a valid bc expression)
    # $2 is number of decimal figures (optional). Defaults to three if none given
    local df=${2:-3}
    printf '%.*f\n' "$df" "$(bc -l <<< "a=$1; if(a>0) a+=5/10^($df+1) else if (a<0) a-=5/10^($df+1); scale=$df; a/1")"
}

试一试:

gniourf$ round "(3+3+4)/3"
3.333
gniourf$ round "(3+3+5)/3"
3.667
gniourf$ round "-(3+3+5)/3"
-3.667
gniourf$ round 0
0.000
gniourf$ round 1/3 10
0.3333333333
gniourf$ round 0.0005
0.001
gniourf$ round 0.00049
0.000

带有-l开关的

1 scale设置为20,这应该足够了。

答案 1 :(得分:2)

下一个函数将参数'x'转换为'd'数字:

define r(x, d) {
    auto r, s

    if(0 > x) {
        return -r(-x, d)
    }
    r = x + 0.5*10^-d
    s = scale
    scale = d
    r = r*10/10
    scale = s  
    return r
} 

答案 2 :(得分:1)

这种解决方案不是那么灵活(它只是将float转换为int),但是可以处理负数:

e=$( echo "scale=0; (${e}+0.5)/1" | bc -l )
if [[ "${e}" -lt 0 ]] ; then
    e=$(( e - 1 ))
fi