Todavía estoy buscando una bc
respuesta pura sobre cómo redondear solo un valor dentro de una función, pero aquí hay una bash
respuesta pura :
#!/bin/bash
echo "Insert the price you want to calculate:"
read float
echo "This is the price without taxes:"
embiggen() {
local int precision fraction=""
if [ "$1" != "${1#*.}" ]; then # there is a decimal point
fraction="${1#*.}" # just the digits after the dot
fi
int="${1%.*}" # the float as a truncated integer
precision="${#fraction}" # the number of fractional digits
echo $(( 10**10 * $int$fraction / 10**$precision ))
}
# round down if negative
if [ "$float" != "${float#-}" ]
then round="-5000000000"
else round="5000000000"
fi
# calculate rounded answer (sans decimal point)
answer=$(( ( `embiggen $float` * 100 + $round ) / `embiggen 1.18` ))
int=${answer%??} # the answer as a truncated integer
echo $int.${answer#$int} # reassemble with correct precision
read -p "Press any key to continue..."
Básicamente, esto extrae cuidadosamente los decimales, multiplica todo por 100 mil millones (10¹⁰, 10**10
in bash
), ajusta la precisión y el redondeo, realiza la división real, divide de nuevo a la magnitud apropiada y luego reinserta el decimal.
Paso a paso:
La embiggen()
función asigna la forma entera truncada de su argumento $int
y guarda los números después del punto $fraction
. El número de dígitos fraccionarios se indica en $precision
. La matemática multiplica 10¹⁰ por la concatenación de $int
y $fraction
luego ajusta eso para que coincida con la precisión (por ejemplo, se embiggen 48.86
convierte en 10¹⁰ × 4886/100 y devuelve 488600000000
488,600,000,000).
Queremos una precisión final de centésimos, por lo que multiplicamos el primer número por 100, sumamos 5 para redondear y luego dividimos el segundo número. Esta asignación de $answer
nos deja en cien veces la respuesta final.
Ahora necesitamos agregar el punto decimal. Asignamos un nuevo $int
valor a la $answer
exclusión de sus dos dígitos finales, luego echo
con un punto y $answer
excluyendo el $int
valor que ya se ha solucionado. (No importa el error de resaltado de sintaxis que hace que esto parezca un comentario)
(Bashismo: la exponenciación no es POSIX, por lo que es un bashismo. Una solución POSIX pura requeriría bucles para agregar ceros en lugar de usar potencias de diez. Además, "embiggen" es una palabra perfectamente cromulante).
Una de las razones principales que uso zsh
como mi shell es que admite matemáticas de punto flotante. La solución a esta pregunta es bastante sencilla en zsh
:
printf %.2f $((float/1.18))
(Me encantaría ver a alguien agregar un comentario a esta respuesta con el truco para habilitar la aritmética de punto flotante bash
, pero estoy bastante seguro de que dicha característica aún no existe).