Я все еще ищу чистый bc
ответ о том, как округлить только одно значение в функции, но вот чистый bash
ответ:
#!/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..."
По сути, это тщательно извлекает десятичные дроби, умножает все на 100 миллиардов (10¹⁰, 10**10
in bash
), корректирует точность и округление, выполняет фактическое деление, делит обратно до соответствующей величины, а затем повторно вводит десятичное число.
Шаг за шагом:
В embiggen()
функции присваивает усечено целым формы его аргумента $int
и сохраняет число после точки в $fraction
. Количество дробных цифр указано в $precision
. В математике умножает 10¹⁰ по конкатенации $int
и , $fraction
а затем корректирует , что соответствует точности (например , embiggen 48.86
становится 10¹⁰ × 4886/100 и возврат 488600000000
которых является 488600000000).
Нам нужна конечная точность в сотых долях, поэтому мы умножаем первое число на 100, добавляем 5 для округления и затем делим второе число. Это назначение $answer
оставляет нам в сто раз окончательный ответ.
Теперь нам нужно добавить десятичную точку. Мы присваиваем новое $int
значение $answer
исключению двух последних цифр, затем echo
оно ставится точкой и $answer
исключает $int
значение, о котором уже позаботились. (Не берите в голову ошибку подсветки синтаксиса, которая заставляет это походить на комментарий)
(Bashism: возведение в степень не является POSIX, так что это bashism. Чистое решение POSIX потребовало бы циклов для добавления нулей, а не использования степеней десяти. Кроме того, «embiggen» - совершенно непонятное слово.)
Одна из основных причин, по которой я использую zsh
свою оболочку, заключается в том, что она поддерживает математику с плавающей запятой. Решение этого вопроса довольно простое в zsh
:
printf %.2f $((float/1.18))
(Я бы хотел, чтобы кто-нибудь добавил комментарий к этому ответу с хитростью, чтобы включить арифметику с плавающей запятой bash
, но я почти уверен, что такой функции еще не существует.)