2014-11-11 34 views
7

Chcę obliczyć średnią z 3 cyframi dziesiętnymi, zaokrąglonymi do najbliższych, przy użyciu bc.Zaokrąglanie liczb za pomocą bc w Bash

Na przykład:

średnio 3, 3 i 5, należy uzyskując 3.667

i

średnią 3, 3 i 4 należy otrzymując 3,333

Próbowałem:

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

ale scale nie zachowuje się tak, jak się spodziewam. Co mogę zrobić, aby rozwiązać mój problem?

+4

Ty dodanie '0.0005', więc' bc' chętnie odpowie z 4 cyfr po przecinku. –

+0

Co więc powinienem zrobić? –

+0

Co powiesz na usunięcie '+ 0.0005'? –

Odpowiedz

4

Twoja sztuczka dodania 0.0005 nie jest złym pomysłem. Chociaż nie działa to w ten sposób. scale jest używany wewnętrznie, gdy bc wykonuje niektóre operacje (takie jak podziały).

W twoim przypadku, to byłoby lepiej, aby wykonać podział pierwsze, być może przy użyciu dużej scale lub przełącznik -l do bc (jeśli wersja obsługuje go), a następnie dodać 0.0005 a następnie ustawić scale=3 i wykonują operacja z udziałem scale wewnętrznie w celu wykonania obcięcia.

Coś jak:

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

Oczywiście, będziemy chcieli, aby postępować inaczej, czy sum jest dodatnia lub ujemna. Na szczęście bc ma kilka operatorów warunkowych.

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

Następnie należy sformatować tę odpowiedź za pomocą printf.

Owinięty w funkcji round (gdzie opcjonalnie można wybrać ilość liczb po przecinku):

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")" 
} 

Wypróbuj go:

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 

z przełącznikiem -l, scale jest ustawiony na 20, co powinno wystarczyć.

+2

Dziękuję! to działa. Ale wydaje się, że muszę dużo pracować, aby napisać kody takie jak ten –

+0

Pracowałem nad C++ i było to łatwe, ponieważ składnia nie była ważna –

+0

Jak rozumiem składnię (przestrzeń itd.) Bardzo ważne w Bash –

1

Następny funkcja runda argumentem 'x' do 'D' cyfr:

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 
} 
Powiązane problemy