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