Für eine höhere Präzision mit (GNU) awk (mit kompiliertem Bignum) verwenden Sie:
$ echo '0.4970436865354813' | awk -M -v PREC=100 '{printf("%.18f\n", $1)}'
0.497043686535481300
PREC = 100 bedeutet 100 Bit anstelle der Standardbits von 53 Bit.
Wenn diese awk nicht verfügbar ist, verwenden Sie bc
$ echo '0.4970436865354813*1.1' | bc -l
.54674805518902943
Oder Sie müssen lernen, mit der inhärenten Ungenauigkeit von Schwimmern zu leben.
In Ihren ursprünglichen Zeilen gibt es mehrere Probleme:
- Ein Faktor von 1,1 ist eine Erhöhung um 10%, nicht um 1% (sollte ein Multiplikator von 1,01 sein). Ich werde 10% verwenden.
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
.
$ a='0.4970436865354813'
$ echo "$a" | awk '{printf("%.16f\n", $1*1.1)}'
0.5467480551890295
$ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.16f\n", $1)}'
0.5467480000000000
Das printf-Format g
entfernt nachgestellte Nullen:
$ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.16g\n", $1)}'
0.546748
$ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.17g\n", $1)}'
0.54674800000000001
Beide Probleme könnten gelöst werden mit:
$ echo "$a" | awk '{printf("%.17g\n", $1*1.1)}'
0.54674805518902947
Oder
$ echo "$a" | awk -v CONVFMT=%.30g '{gsub($1, $1*1.1)}; {printf("%.17f\n", $1)}'
0.54674805518902947
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.
$ echo "$a" | awk -v CONVFMT=%.30g '{gsub($1, $1*1.1}; {printf("%.30f\n", $1)}'
0.546748055189029469325134868996
Der richtige Wert ist:
$ echo "scale=18; 0.4970436865354813 * 1.1" | bc
.54674805518902943
Was auch mit (GNU) awk berechnet werden könnte, wenn die Bignumbibliothek kompiliert wurde in:
$ echo "$a" | awk -M -v PREC=100 -v CONVFMT=%.30g '{printf("%.30f\n", $1)}'
0.497043686535481300000000000000