Siguiente función redondea el argumento 'x' a 'd' dígitos:
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
}
Tu truco para agregar 0.0005 no es mala idea Sin embargo, no funciona de esa manera. scale se usa internamente cuando bc realiza algunas operaciones (como divisiones).
En tu caso, sería mejor realizar la división primero, quizás usando un scale grande o el -l cambia a bc (si su versión lo admite), luego agregue 0.0005 y luego establecer scale=3 y realizar una operación que involucre scale internamente para realizar el truncamiento.
Algo como:
`a=$sum/$n+0.0005; scale=3; a/1`
Por supuesto, querrá proceder de manera diferente si sum es positivo o negativo. Afortunadamente, bc tiene algunos operadores condicionales.
`a=$sum/$n; if(a>0) a+=0.0005 else if (a<0) a-=0.0005; scale=3; a/1`
Luego querrá formatear esta respuesta usando printf .
Envuelto en una función round (donde puede seleccionar opcionalmente el número de cifras decimales):
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")"
}
Pruébalo:
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
con el -l interruptor, scale está establecido en 20 , que debería ser suficiente.
Esta solución no es tan flexible (simplemente convierte float a int), pero puede manejar números negativos:
e=$( echo "scale=0; (${e}+0.5)/1" | bc -l )
if [[ "${e}" -lt 0 ]] ; then
e=$(( e - 1 ))
fi