Округление чисел с bc в Bash

Я хочу вычислить среднее значение с 3 десятичными цифрами, округленными до ближайшего, используя bc.

например:

среднее 3, 3 и 5 должно дать 3,667

и

среднее значение 3, 3 и 4 должно дать 3,333

пробовал:

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

но scale ведет себя не так, как я ожидаю. Что я могу сделать, чтобы решить свою проблему?

2 ответов


ваш трюк, чтобы добавить 0.0005 неплохая идея. Хотя, это не совсем так. scale используется внутри, когда bc выполняет некоторые операции (например, деление).

в вашем случае было бы лучше сначала выполнить деление, возможно, используя большой scale или -l переключатель bc1 (если ваша версия поддерживает его), то добавьте 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() {
    #  is expression to round (should be a valid bc expression)
    #  is number of decimal figures (optional). Defaults to three if none given
    local df=${2:-3}
    printf '%.*f\n' "$df" "$(bc -l <<< "a=; 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

1 С -l переключатель scale установлено значение 20, которого должно быть достаточно.


следующая функция круглый аргумент ' 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
}