Ich bin noch auf der Suche nach einem reinen bc
Antwort, um nur einen Wert innerhalb einer Funktion zu runden, aber hier ist eine reine bash
Antwort:
#!/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..."
Grundsätzlich werden dabei die Dezimalstellen sorgfältig extrahiert und alles mit 100 Milliarden multipliziert (10¹⁰, 10**10
in bash
) , auf Genauigkeit und Rundung korrigiert, die eigentliche Division ausgeführt, auf die entsprechende Größe zurückgeteilt und die Dezimalstelle erneut eingefügt.
Schritt für Schritt:
Die embiggen()
Funktion weist die abgeschnittene Ganzzahlform ihres Arguments zu $int
und speichert die Zahlen nach dem Punkt in $fraction
. Die Anzahl der Nachkommastellen ist in angegeben $precision
. Die Mathematik multipliziert 10¹⁰ mit der Verkettung von $int
und $fraction
passt diese dann an die Genauigkeit an (z. B. embiggen 48.86
wird 10¹⁰ × 488600000000
4886/100 und ergibt 488.600.000.000).
Wir wollen eine endgültige Genauigkeit von Hundertsteln, also multiplizieren wir die erste Zahl mit 100, addieren 5 zu Rundungszwecken und dividieren dann die zweite Zahl. Diese Zuordnung $answer
lässt uns hundertmal die endgültige Antwort.
Jetzt müssen wir den Dezimalpunkt hinzufügen. Wir weisen $int
dem $answer
Ausschluss der letzten beiden Ziffern einen neuen Wert zu , dann den echo
mit einem Punkt und dem$answer
Ausschluss des $int
Werts, für den bereits gesorgt wurde. (Egal, welcher Syntax-Highlighting-Fehler dies wie einen Kommentar erscheinen lässt.)
(Bashismus: Potenzierung ist nicht POSIX, also ist dies ein Bashismus. Eine reine POSIX-Lösung würde Schleifen erfordern, um Nullen hinzuzufügen, anstatt Zehnerpotenzen zu verwenden. Außerdem ist "embiggen" ein perfekt kromulantes Wort.)
Einer der Hauptgründe, warum ich zsh
als Shell verwende, ist die Unterstützung von Gleitkomma-Mathematik. Die Lösung dieser Frage liegt auf der Hand in zsh
:
printf %.2f $((float/1.18))
(Ich würde gerne jemanden sehen, der dieser Antwort einen Kommentar mit dem Trick hinzufügt, Gleitkomma-Arithmetik zu aktivieren bash
, aber ich bin mir ziemlich sicher, dass es eine solche Funktion noch nicht gibt.)