Nächste Funktion rundet Argument 'x' auf 'd' Ziffern:
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
}
Ihr Trick, um 0.0005
hinzuzufügen ist keine schlechte Idee. Allerdings funktioniert das nicht ganz so. scale
wird intern verwendet, wenn bc
führt einige Operationen durch (wie Divisionen).
In Ihrem Fall wäre es besser, zuerst die Division durchzuführen, vielleicht mit einer großen scale
oder die -l
wechseln Sie zu bc
(falls Ihre Version dies unterstützt), fügen Sie dann 0.0005
hinzu und dann scale=3
einstellen und führen Sie eine Operation mit scale
durch intern, um die Kürzung durchführen zu lassen.
Etwas wie:
`a=$sum/$n+0.0005; scale=3; a/1`
Natürlich möchten Sie anders vorgehen, ob sum
positiv oder negativ ist. Zum Glück bc
hat einige bedingte Operatoren.
`a=$sum/$n; if(a>0) a+=0.0005 else if (a<0) a-=0.0005; scale=3; a/1`
Sie sollten diese Antwort dann mit printf
formatieren .
Eingehüllt in eine Funktion round
(wobei Sie optional die Anzahl der Nachkommastellen auswählen können):
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")"
}
Versuchen Sie es:
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
mit dem -l
Schalter, scale
auf 20
eingestellt ist , was ausreichen sollte.
Diese Lösung ist nicht so flexibel (sie wandelt nur Float in Int um), aber sie kann mit negativen Zahlen umgehen:
e=$( echo "scale=0; (${e}+0.5)/1" | bc -l )
if [[ "${e}" -lt 0 ]] ; then
e=$(( e - 1 ))
fi