Я все еще ищу чистого bc
ответ на вопрос о том, как округлить только одно значение внутри функции, но вот чистый bash
ответ:
#!/bin/bashecho "Insert the price you want to calculate:"read floatecho "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 negativeif [ "$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 integerecho $int.${answer#$int} # reassemble with correct precisionread -p "Press any key to continue..."
По сути, это тщательно извлекает десятичные дроби, умножает все на 100 миллиардов (101⁰, 10**10
в bash
), настраивает точность и округление, выполняет фактическое деление, делит обратно на соответствующую величину, а затем повторно вставляет десятичную дробь.
Шаг за шагом:
То embiggen()
функция присваивает усеченную целочисленную форму своего аргумента $int
и сохраняет числа после точки в $fraction
. Количество дробных цифр указывается в $precision
. Математика умножает 101⁰ на объединение $int
и $fraction
а затем настраивает его в соответствии с точностью (например embiggen 48.86
становится 101⁰ × 4886 / 100 и возвращает 488600000000
что составляет 488 600 000 000).
Нам нужна конечная точность в сотых долях, поэтому мы умножаем первое число на 100, добавляем 5 для округления, а затем делим второе число. Это назначение $answer
оставляет нам в сто раз больший окончательный ответ.
Теперь нам нужно добавить десятичную точку. Мы назначаем новый $int
ценность для $answer
исключая его последние две цифры, тогда echo
это с точкой и $answer
исключая $int
ценность, о которой уже позаботились. (Не обращайте внимания на ошибку подсветки синтаксиса, из-за которой это выглядит как комментарий)
(Башизм: возведение в степень - это не POSIX, так что это башизм. Чистое решение POSIX потребовало бы циклов для добавления нулей, а не использования степеней десяти. Кроме того, "эмбигген" - это совершенно подходящее слово.)
Одна из главных причин, по которой я использую zsh
поскольку моя оболочка такова, что она поддерживает математику с плавающей запятой. Решение этого вопроса довольно простое в zsh
:
printf %.2f $((float/1.18))
(Я бы хотел, чтобы кто-нибудь добавил комментарий к этому ответу с помощью хитрости для включения арифметики с плавающей запятой в bash
, но я почти уверен, что такой функции еще не существует.)