Ich suche nach einer Möglichkeit, awk anzuweisen, in einer Substitutionsoperation hochpräzise Arithmetik durchzuführen. Dazu müssen Sie ein Feld aus einer Datei lesen und durch ein Inkrement von 1% für diesen Wert ersetzen. Dort verliere ich jedoch an Präzision. Hier ist eine vereinfachte Reproduktion des Problems:
$ echo 0.4970436865354813 | awk '{gsub($1, $1*1.1)}; {print}'
0.546748
Hier habe ich eine 16-stellige Nachkommastelle, aber awk gibt nur sechs. Mit printf erhalte ich das gleiche Ergebnis:
$ echo 0.4970436865354813 | awk '{gsub($1, $1*1.1)}; {printf("%.16G\n", $1)}'
0.546748
Irgendwelche Vorschläge, wie man die gewünschte Präzision erreicht?
gsub
ist dies nicht erforderlich . Das Problem besteht darin, dassgsub
Zeichenfolgen und keine Zahlen verwendet werden. Daher wird zuerst eine Konvertierung durchgeführtCONVFMT
, und der Standardwert dafür ist%.6g
.Antworten:
Oder besser gesagt hier:
ist wahrscheinlich das Beste, was Sie erreichen können. Verwenden Sie
bc
stattdessen für eine beliebige Genauigkeit.quelle
AWK
, können Sie das-M
Flag verwenden und denPREC
Wert auf eine große Zahl setzenFür eine höhere Präzision mit (GNU) awk (mit kompiliertem Bignum) verwenden Sie:
PREC = 100 bedeutet 100 Bit anstelle der Standardbits von 53 Bit.
Wenn diese awk nicht verfügbar ist, verwenden Sie bc
Oder Sie müssen lernen, mit der inhärenten Ungenauigkeit von Schwimmern zu leben.
In Ihren ursprünglichen Zeilen gibt es mehrere Probleme:
Das Konvertierungsformat von einer Zeichenfolge in eine (schwebende) Zahl wird von CONVFMT angegeben. Der Standardwert ist
%.6g
. Dadurch werden die Werte auf 6 Dezimalstellen (nach dem Punkt) begrenzt. Dies gilt für das Ergebnis der gsub-Änderung von$1
.Das printf-Format
g
entfernt nachgestellte Nullen:Beide Probleme könnten gelöst werden mit:
Oder
Aber denken Sie nicht daran, dass dies eine höhere Präzision bedeutet. Die interne Zahlendarstellung ist immer noch ein Float in doppelter Größe. Das bedeutet 53 Bit Genauigkeit und damit können Sie nur sicher sein, dass 15 Dezimalstellen korrekt sind, selbst wenn bis zu 17 Stellen korrekt aussehen. Das ist ein Trugbild.
Der richtige Wert ist:
Was auch mit (GNU) awk berechnet werden könnte, wenn die Bignumbibliothek kompiliert wurde in:
quelle