Ainda estou procurando uma resposta bc
pura sobre como arredondar apenas um valor em uma função, mas aqui está uma resposta bash
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..."
Basicamente, isso cuidadosamente extrai os decimais, multiplica tudo em 100 bilhões (10¹⁰, 10**10
em bash
), ajusta a precisão e o arredondamento, executa a divisão real, divide de volta à magnitude apropriada e, em seguida, reinsere o decimal.
Passo-a-passo:
A função embiggen()
atribui a forma inteira truncada de seu argumento a $int
e salva os números após o ponto em $fraction
. O número de dígitos fracionários é anotado em $precision
. A matemática multiplica 10¹⁰ pela concatenação de $int
e $fraction
e depois ajusta isso para corresponder à precisão (por exemplo, embiggen 48.86
se torna 10 × 4886/100 e retorna 488600000000
, que é 488.600.000.000).
Queremos uma precisão final de centésimos, então multiplicamos o primeiro número por 100, adicionamos 5 para fins de arredondamento e depois dividimos o segundo número. Esta atribuição de $answer
nos deixa cem vezes a resposta final.
Agora precisamos adicionar o ponto decimal. Atribuímos um novo valor de $int
a $answer
, excluindo seus dois dígitos finais, em seguida, echo
com um ponto e o $answer
excluindo o valor $int
que já foi resolvido. (Não importa o erro de realce de sintaxe que faz parecer um comentário)
(Bashism: a exponenciação não é POSIX, então isso é um bashumano. Uma solução POSIX pura exigiria loops para adicionar zeros ao invés de usar potências de 10. Além disso, "embiggen" é uma palavra perfeitamente cromulativa.)
Uma das principais razões pelas quais eu uso zsh
como meu shell é que ele suporta matemática de ponto flutuante. A solução para essa questão é bem direta em zsh
:
printf %.2f $((float/1.18))
(Eu adoraria ver alguém adicionar um comentário a essa resposta com o truque de ativar a aritmética de ponto flutuante em bash
, mas tenho certeza de que esse recurso ainda não existe.)