เพื่อความแม่นยำที่สูงขึ้นด้วย (GNU) awk (ด้วยการรวบรวม bignum ใน):
$ echo '0.4970436865354813' | awk -M -v PREC=100 '{printf("%.18f\n", $1)}'
0.497043686535481300
PREC = 100 หมายถึง 100 บิตแทนค่าเริ่มต้น 53 บิต
หาก awk นั้นไม่พร้อมใช้งานให้ใช้ bc
$ echo '0.4970436865354813*1.1' | bc -l
.54674805518902943
หรือคุณจะต้องเรียนรู้ที่จะอยู่กับความไม่แน่นอนของการลอยตัว
ในบรรทัดเดิมของคุณมีปัญหาหลายประการ:
- ปัจจัย 1.1 คือเพิ่มขึ้น 10% ไม่ใช่ 1% (ควรเป็นตัวคูณ 1.01) ฉันจะใช้ 10%
รูปแบบการแปลงจากสตริงไปยังหมายเลข (ลอย) ถูกกำหนดโดย CONVFMT %.6g
ค่าเริ่มต้นของมันคือ ที่ จำกัด ค่าไว้ที่ 6 หลักทศนิยม (หลังจุด) ที่ถูกนำไปใช้กับผลของการเปลี่ยนแปลง gsub $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
รูปแบบ printf g
ลบศูนย์ต่อท้าย:
$ 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
ปัญหาทั้งสองสามารถแก้ไขได้ด้วย:
$ echo "$a" | awk '{printf("%.17g\n", $1*1.1)}'
0.54674805518902947
หรือ
$ echo "$a" | awk -v CONVFMT=%.30g '{gsub($1, $1*1.1)}; {printf("%.17f\n", $1)}'
0.54674805518902947
แต่อย่าเข้าใจว่านี่หมายถึงความแม่นยำสูงกว่า การแสดงตัวเลขภายในยังคงเป็นแบบทศนิยมสองเท่า นั่นหมายถึงความแม่นยำ 53 บิตโดยที่คุณสามารถมั่นใจได้ว่ามีทศนิยม 15 หลักที่ถูกต้องแม้ว่าจำนวนครั้งมากถึง 17 หลักจะดูถูกต้อง นั่นเป็นภาพลวงตา
$ echo "$a" | awk -v CONVFMT=%.30g '{gsub($1, $1*1.1}; {printf("%.30f\n", $1)}'
0.546748055189029469325134868996
ค่าที่ถูกต้องคือ:
$ echo "scale=18; 0.4970436865354813 * 1.1" | bc
.54674805518902943
ซึ่งสามารถคำนวณได้ด้วย (GNU) awk หากมีการรวบรวมไลบรารี bignum ใน:
$ echo "$a" | awk -M -v PREC=100 -v CONVFMT=%.30g '{printf("%.30f\n", $1)}'
0.497043686535481300000000000000