Vermeiden Sie Schleifen in Muscheln.
Wenn Sie rechnen möchten, verwenden Sie awk
oder bc
:
awk '
BEGIN{
for (i = 4.00; i < 5.42; i+ = 0.02)
print i
}'
Oder
bc << EOF
for (i = 4.00; i < 5.42; i += 0.02) i
EOF
Beachten Sie, dass awk
(im Gegensatz zu bc
) die double
Gleitkommazahlendarstellung Ihres Prozessors funktioniert (wahrscheinlich IEEE 754- Typ). Da diese Zahlen binäre Annäherungen an diese Dezimalzahlen sind, können Sie einige Überraschungen erleben:
$ gawk 'BEGIN{for (i=0; i<=0.3; i+=0.1) print i}'
0
0.1
0.2
Wenn Sie ein hinzufügen OFMT="%.17g"
, können Sie den Grund für das Fehlen sehen 0.3
:
$ gawk 'BEGIN{OFMT="%.17g"; for (i=0; i<=0.5; i+=0.1) print i}'
0
0.10000000000000001
0.20000000000000001
0.30000000000000004
0.40000000000000002
0.5
bc
macht willkürliche Präzision, hat also kein solches Problem.
Beachten Sie, dass standardmäßig (sofern Sie das Ausgabeformat nicht mit expliziten Formatspezifikationen ändern OFMT
oder printf
mit expliziten Formatspezifikationen awk
verwenden ) die %.6g
Anzeige von Gleitkommazahlen verwendet wird. Wechseln Sie daher für Gleitkommazahlen über 1.000.000 zu 1e6 und höher und kürzen Sie den Bruchteil für hohe Zahlen (100000.02) würde als 100000 angezeigt werden).
Wenn Sie wirklich brauchen eine Shell - Schleife zu verwenden, da zum Beispiel mögen Sie bestimmte Befehle für jede Iteration dieser Schleife laufen, entweder eine Shell verwenden , um mit Gleitkomma - Arithmetik - Unterstützung wie zsh
, yash
oderksh93
oder die Liste der Werte mit einem Befehl zu erzeugen , wie oben (oder seq
falls verfügbar) und durchlaufen den Ausgang.
Mögen:
unset -v IFS # configure split+glob for default word splitting
for i in $(seq 4 0.02 5.42); do
something with "$i"
done
Oder:
seq 4 0.02 5.42 | while IFS= read i; do
something with "$i"
done
Wenn Sie die Grenzen Ihrer Prozessor-Gleitkommazahlen nicht überschreiten, werden seq
Fehler, die durch Gleitkomma-Approximationen auftreten, eleganter behandelt als dieawk
obigen Version.
Wenn Sie keinen seq
(GNU-Befehl) haben, können Sie einen zuverlässigeren Befehl als Funktion wie folgt erstellen:
seq() { # args: first increment last
bc << EOF
for (i = $1; i <= $3; i += $2) i
EOF
}
Das würde besser funktionieren für Dinge wie seq 100000000001 0.000000001 100000000001.000000005
. Beachten Sie jedoch, dass Zahlen mit willkürlich hoher Genauigkeit nicht viel helfen, wenn wir sie an Befehle übergeben, die sie nicht unterstützen.