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