Saya mencari cara untuk memberitahu awk untuk melakukan aritmatika presisi tinggi dalam operasi substitusi. Ini melibatkan, membaca bidang dari file dan menggantinya dengan kenaikan 1% pada nilai itu. Namun, saya kehilangan presisi di sana. Berikut adalah reproduksi masalah yang disederhanakan:
$ echo 0.4970436865354813 | awk '{gsub($1, $1*1.1)}; {print}'
0.546748
Di sini, saya memiliki 16 digit setelah presisi desimal tetapi awk hanya memberikan enam. Menggunakan printf, saya mendapatkan hasil yang sama:
$ echo 0.4970436865354813 | awk '{gsub($1, $1*1.1)}; {printf("%.16G\n", $1)}'
0.546748
Ada saran tentang cara mendapatkan presisi yang diinginkan?
gsub
tidak perlu. Masalahnya adalahgsub
bekerja pada string, bukan angka, jadi konversi dilakukan terlebih dahulu menggunakanCONVFMT
, dan nilai default untuk itu adalah%.6g
.Jawaban:
Atau lebih tepatnya di sini:
mungkin yang terbaik yang bisa Anda capai. Gunakan
bc
sebagai gantinya untuk presisi sewenang-wenang.sumber
AWK
Anda dapat menggunakan-M
bendera dan mengaturPREC
nilainya ke sejumlah besarUntuk presisi yang lebih tinggi dengan (GNU) awk (dengan bignum dikompilasi dalam) gunakan:
PREC = 100 berarti 100 bit, bukan 53 bit default.
Jika awk itu tidak tersedia, gunakan bc
Atau Anda perlu belajar hidup dengan ketidaktepatan mengapung yang melekat.
Di baris asli Anda ada beberapa masalah:
Format konversi dari string ke angka (mengambang) diberikan oleh CONVFMT. Nilai standarnya adalah
%.6g
. Itu membatasi nilai hingga 6 digit desimal (setelah titik). Itu diterapkan pada hasil perubahan gsub dari$1
.Format printf
g
menghapus nol tambahan:Kedua masalah tersebut dapat diselesaikan dengan:
Atau
Tetapi jangan mengerti bahwa ini berarti presisi yang lebih tinggi. Representasi nomor internal masih mengambang dalam ukuran ganda. Itu berarti 53 bit presisi dan dengan itu Anda hanya bisa memastikan 15 digit desimal yang benar, bahkan jika berkali-kali hingga 17 digit terlihat benar. Itu fatamorgana.
Nilai yang benar adalah:
Yang dapat juga dihitung dengan (GNU) awk jika perpustakaan bignum telah dikompilasi dalam:
sumber