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