2014-11-11 4 views
7

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

Например:

средние 3, 3 и 5 следует, получая 3.667

и

средних 3, 3 и 4 следует, получая 3.333

Я пробовал:

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

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

+4

Вы хотите добавить '0.0005', так' bc' охотно отвечает 4 цифры после запятой. –

+0

Так что мне делать? –

+0

Как насчет вас удалить '+ 0,0005'? –

ответ

4

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

В вашем случае, это было бы лучше выполнить разделение первым, может быть, с использованием большого scale или -l переключателя в bc (если ваша версия поддерживает его), а затем добавить 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, scale установлен в 20, которого должно быть достаточно.

+2

Спасибо! оно работает. Но, похоже, мне нужно много работать, чтобы писать коды, подобные этому –

+0

Я работал на C++, и это было легко, потому что синтаксис was not important –

+0

Как я понимаю синтаксис (космос .. и т. Д.) Очень важен в Bash –

1

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