Ich versuche, zwei Bildbreiten in einem Bash-Skript zu teilen, aber Bash gibt mir 0
als Ergebnis:
RESULT=$(($IMG_WIDTH/$IMG2_WIDTH))
Ich habe den Bash-Leitfaden studiert und weiß, dass ich ihn bc
in allen Beispielen im Internet verwenden sollte bc
. In echo
ich die gleiche Sache in meinem zu setzen versucht , SCALE
aber es hat nicht funktioniert.
Hier ist das Beispiel, das ich in den Tutorials gefunden habe:
echo "scale=2; ${userinput}" | bc
Wie kann ich Bash dazu bringen, mir einen Schwimmer zu geben 0.5
?
bash
floating-point
arithmetic-expressions
Medya Gh
quelle
quelle
Antworten:
Das kannst du nicht. Bash macht nur ganze Zahlen; Sie müssen an ein Tool wie z
bc
.quelle
VAR=$(echo "scale=2; $IMG_WIDTH/$IMG2_WIDTH" | bc)
oderVAR=$(bc <<<"scale=2;$IMG_WIDTH/$IMG2_WIDTH")
ohne $ (()) (doppelte Klammern); die durch die Bash vor der Ausführung des Befehls erweitert wirddu kannst das:
UPDATE
20130926
: Sie können verwenden:quelle
bc -l <<< 'scale=2; 100/3'
Unless specifically mentioned the scale of the result is the maximum scale of the expressions involved.
Und es gibt einen zusätzlichen Hinweis für den/
Bediener:The scale of the result is the value of the variable scale.
bc <<< 'scale=1; 1*3.00001'
Skala ist aus irgendeinem Grund wirklich 5,bc <<< 'scale=1; 1/3.000001'
Skala ist 1. Interessanterweise setzt das Teilen durch 1 es gerade:bc <<< 'scale=1; 1*3.00001/1'
Skala ist 1Bash
Wie von anderen angemerkt,
bash
unterstützt keine Gleitkomma-Arithmetik, obwohl Sie sie mit einem Trick mit festen Dezimalstellen vortäuschen könnten, z. B. mit zwei Dezimalstellen:Ausgabe:
Siehe Nilfreds Antwort für einen ähnlichen, aber präziseren Ansatz.
Alternativen
Neben den genannten
bc
undawk
Alternativen gibt es auch folgende:clisp
mit bereinigter Ausgabe:
oder durch stdin:
dc
Genius Cli Rechner
Ghostscript
Gnuplot
jq
Oder:
ksh
lua
oder durch stdin:
Maxima
mit bereinigter Ausgabe:
Knoten
Oktave
perl
python2
python3
R.
mit bereinigter Ausgabe:
Rubin
wcalc
Mit bereinigter Ausgabe:
zsh
Einheiten
Mit kompakter Ausgabe:
Andere Quellen
Stéphane Chazelas beantwortete eine ähnliche Frage unter Unix.SX.
quelle
echo 1/3 | node -p
ist kurz.Die Antwort von Marvin ein wenig verbessern:
bc kommt nicht immer als installiertes Paket.
quelle
exit
, um zu verhindern, dass es aus seinem Eingabestream liest. Ich schlage auch vor, awk--v
Flaggen zu verwenden, um das Leaning-Zahnstochersyndrom zu verhindern. Also:RESULT=$(awk -v dividend="${IMG_WIDTH}" -v divisor="${IMG2_WIDTH}" 'BEGIN {printf "%.2f", dividend/divisor; exit(0)}')
RESULT=$(awk '{printf("result= %.2f\n",$1/$2)}' <<<" $IMG_WIDTH $IMG2_WIDTH "
.bc
ist Teil von POSIX und wird normalerweise vorinstalliert.Sie können bc mit der
-l
Option (dem L-Buchstaben) verwenden.quelle
-l
in mein System einbeziehe, führt bc keine Gleitkomma-Mathematik durch.Alternativ zu bc können Sie awk in Ihrem Skript verwenden.
Beispielsweise:
Oben weist "% .2f" die Funktion printf an, eine Gleitkommazahl mit zwei Ziffern nach der Dezimalstelle zurückzugeben. Ich habe Echo verwendet, um die Variablen als Felder weiterzuleiten, da awk sie ordnungsgemäß verarbeitet. "$ 1" und "$ 2" beziehen sich auf das erste und zweite Feld, die in awk eingegeben werden.
Und Sie können das Ergebnis als eine andere Variable speichern, indem Sie:
quelle
Es ist die perfekte Zeit, um zsh, eine (fast) Bash-Obermenge, mit vielen zusätzlichen netten Funktionen, einschließlich Gleitkomma-Mathematik, auszuprobieren. So würde Ihr Beispiel in zsh aussehen:
Dieser Beitrag kann Ihnen helfen: bash - Lohnt es sich, für den gelegentlichen Gebrauch auf zsh zu wechseln?
quelle
Nun, bevor float eine Zeit war, in der feste Dezimalstellenlogik verwendet wurde:
Die letzte Zeile ist ein Bashim. Wenn Sie Bash nicht verwenden, versuchen Sie stattdessen diesen Code:
Das Grundprinzip des Codes lautet: Multiplizieren Sie mit 100, bevor Sie dividieren, um 2 Dezimalstellen zu erhalten.
quelle
Wenn Sie die gewünschte Variante gefunden haben, können Sie sie auch in eine Funktion einbinden.
Hier wickle ich etwas Bashismus in eine Div-Funktion ein:
Einzeiler:
Oder mehrzeilig:
Jetzt haben Sie die Funktion
und benutze es gerne
UPDATE Ich habe ein kleines Skript hinzugefügt, das Ihnen die grundlegenden Operationen mit Gleitkommazahlen für Bash bietet:
Verwendung:
Und hier das Drehbuch:
quelle
local _d=${3:-2}
ist einfacherEs ist nicht wirklich Gleitkomma, aber wenn Sie etwas wollen, das mehr als ein Ergebnis in einem Aufruf von bc setzt ...
berechnet die Fläche und den Durchmesser eines Kreises, dessen Radius in $ 1 angegeben ist
quelle
Es gibt Szenarien, in denen Sie bc nicht verwenden können, da es möglicherweise einfach nicht vorhanden ist, wie in einigen reduzierten Versionen von Busybox oder eingebetteten Systemen. In jedem Fall ist es immer eine gute Sache, äußere Abhängigkeiten zu begrenzen. Sie können der Zahl, die durch (Zähler) geteilt wird, immer Nullen hinzufügen. Dies entspricht dem Multiplizieren mit einer Potenz von 10 (Sie sollten eine Potenz von 10 entsprechend wählen die Genauigkeit, die Sie benötigen), wodurch die Division eine ganzzahlige Zahl ausgibt. Sobald Sie diese Ganzzahl haben, behandeln Sie sie als Zeichenfolge und positionieren Sie den Dezimalpunkt (von rechts nach links verschieben) mehrmals entsprechend der Zehnerpotenz, mit der Sie den Zähler multipliziert haben. Dies ist eine einfache Methode, um Float-Ergebnisse zu erhalten, indem nur ganzzahlige Zahlen verwendet werden.
quelle
Während Sie in Bash keine Gleitkommadivision verwenden können, können Sie die Festkommadivision verwenden. Alles, was Sie tun müssen, ist, Ihre ganzen Zahlen mit einer Potenz von 10 zu multiplizieren und dann den ganzzahligen Teil zu dividieren und eine Modulo-Operation zu verwenden, um den gebrochenen Teil zu erhalten. Nach Bedarf runden.
quelle
Ich weiß, es ist alt, aber zu verlockend. Die Antwort lautet also: Du kannst nicht ... aber du kannst es irgendwie. Lass uns das versuchen:
Auf diese Weise erhalten Sie 2 Ziffern nach dem Punkt, abgeschnitten (nennen Sie es Rundung nach unten, haha) in reiner Bash (keine Notwendigkeit, andere Prozesse zu starten). Wenn Sie nach dem Punkt nur eine Ziffer benötigen, multiplizieren Sie natürlich mit 10 und machen Modulo 10.
was das macht:
Bonustrack : Die bc-Version x 1000 dauerte auf meinem Laptop 1,8 Sekunden, während die reine Bash-Version 0,016 Sekunden dauerte.
quelle
So führen Sie Gleitkommaberechnungen in Bash durch:
Anstatt " here strings " (
<<<
) mit dembc
Befehl zu verwenden, wie es eines der am häufigsten bewerteten Beispiele tut, ist hier mein bevorzugtesbc
Gleitkomma-Beispiel direkt aus demEXAMPLES
Abschnitt derbc
Manpages (sieheman bc
für die Handbuchseiten).Bevor wir beginnen, wissen Sie, dass eine Gleichung für pi lautet :
pi = 4*atan(1)
.a()
unten ist diebc
mathematische Funktion füratan()
.So speichern Sie das Ergebnis einer Gleitkommaberechnung in einer Bash-Variablen - in diesem Fall in einer aufgerufenen Variablen
pi
. Beachten Sie, dassscale=10
in diesem Fall die Anzahl der Dezimalstellen mit einer Genauigkeit von 10 festgelegt wird. Nach dieser Stelle stehende Dezimalstellen werden abgeschnitten .Um nun eine einzige Codezeile zu haben, die auch den Wert dieser Variablen ausgibt, fügen Sie den
echo
Befehl einfach wie folgt als Folgebefehl am Ende hinzu. Beachten Sie die Anweisung mit 10 Dezimalstellen, wie befohlen:Lassen Sie uns zum Schluss eine Rundung einwerfen. Hier verwenden wir die
printf
Funktion, um auf 4 Dezimalstellen zu runden. Beachten Sie, dass die3.14159...
Runden jetzt zu3.1416
. Da wir runden, müssen wir nicht mehrscale=10
auf 10 Dezimalstellen kürzen, also entfernen wir einfach diesen Teil. Hier ist die Endlösung:Hier ist eine weitere wirklich großartige Anwendung und Demo der oben genannten Techniken: Messen und Drucken der Laufzeit.
Beachten Sie, dass
dt_min
von gerundet wird0.01666666666...
zu0.017
:Verbunden:
quelle
Verwenden Sie calc. Es ist das einfachste Beispiel, das ich gefunden habe:
quelle
Für diejenigen, die versuchen, Prozentsätze mit der akzeptierten Antwort zu berechnen, aber an Genauigkeit verlieren:
Wenn Sie dies ausführen:
Sie erhalten
99.00
nur, was an Präzision verliert.Wenn Sie es so ausführen:
Jetzt verstehst du
99.99
.Weil Sie nur zum Zeitpunkt des Druckens skalieren.
Siehe hier
quelle
** Injektionssichere Gleitkomma-Mathematik in Bash / Shell **
Hinweis: Der Schwerpunkt dieser Antwort liegt auf der Bereitstellung von Ideen für eine injektionssichere Lösung für die Durchführung von Mathematik in Bash (oder anderen Shells). Dies kann natürlich mit geringfügigen Anpassungen verwendet werden, um eine erweiterte Zeichenfolgenverarbeitung usw. durchzuführen.
Die meisten der vorgestellten Lösungen erstellen ein kleines Scriptlet im laufenden Betrieb unter Verwendung externer Daten (Variablen, Dateien, Befehlszeile, Umgebungsvariablen). Die externe Eingabe kann verwendet werden, um schädlichen Code in die Engine einzufügen, viele davon
Nachfolgend finden Sie einen Vergleich zur Verwendung der verschiedenen Sprachen zur Durchführung grundlegender mathematischer Berechnungen, wobei das Ergebnis Gleitkommawerte sind. Es berechnet A + B * 0,1 (als Gleitkomma).
Bei allen Lösungsversuchen wird vermieden, dass dynamische Scriptlets erstellt werden, die extrem schwer zu warten sind. Stattdessen verwenden sie ein statisches Programm und übergeben Parameter an die angegebene Variable. Sie können sicher mit Parametern mit Sonderzeichen umgehen, wodurch die Möglichkeit der Code-Injection verringert wird. Die Ausnahme ist 'BC', das keine Eingabe- / Ausgabefunktion bietet
Die Ausnahme ist 'bc', das keine Eingabe / Ausgabe liefert, alle Daten kommen über Programme in stdin und alle Ausgaben gehen an stdout. Alle Berechnungen werden in einer Sandbox ausgeführt, die keine Nebenwirkungen zulässt (Öffnen von Dateien usw.). Theoretisch spritzwassergeschützt!
quelle
python3 -c 'import sys ; *a, = map(float, sys.argv[1:]) ; print(a[0] + a[1]*0.1 + a[2])' "$A" "$B"
"4200.0" ==> 4205.63Hier ist der Befehl awk: -F = Feldtrennzeichen == +
quelle