Я все ще шукаю чисту 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
в bash
), підлаштовується для точності і округлення, преформ фактичного поділу, ділить назад відповідному величині, а потім повторно вставляє десяткову.
Крок за кроком:
У embiggen()
функції привласнює усечено цілим форми його аргументу $int
і зберігає число після точки в $fraction
. Кількість дробових цифр зазначається в $precision
. В математиці примножує 10¹⁰ по конкатенації $int
і , $fraction
а потім коригує , що відповідає точності (наприклад , embiggen 48.86
стає 10¹⁰ × 4886/100 і повернення 488600000000
яких є +488600000000).
Ми хочемо остаточної точності сотих, тому множимо перше число на 100, додаємо 5 для цілей округлення, а потім ділимо друге число. Це завдання $answer
залишає нас у стократно остаточній відповіді.
Тепер нам потрібно додати десяткову точку. Нове $int
значення ми присвоюємо $answer
виключенню останніх двох цифр, потім - echo
з крапкою та $answer
виключенням $int
значення, про яке вже було зроблено. (Незважаючи на помилку підсвічування синтаксису, яка робить це схожим на коментар)
(Башизм: експоненція - це не POSIX, тому це башізм. Чисте рішення POSIX вимагає, щоб петлі додавали нулі, а не використовували потужність десяти. Також "embiggen" - це ідеально кромулююче слово.)
Однією з головних причин, яку я використовую zsh
як свою оболонку, є те, що вона підтримує математику з плаваючою комою. Вирішення цього питання досить просте в zsh
:
printf %.2f $((float/1.18))
(Мені б хотілося, щоб хтось додав коментар до цієї відповіді з трюком, щоб включити арифметику з плаваючою комою bash
, але я впевнений, що така функція ще не існує.)