Để có độ chính xác cao hơn với (GNU) awk (với bignum được biên dịch), hãy sử dụng:
$ echo '0.4970436865354813' | awk -M -v PREC=100 '{printf("%.18f\n", $1)}'
0.497043686535481300
PREC = 100 có nghĩa là 100 bit thay vì 53 bit mặc định.
Nếu awk đó không có sẵn, sử dụng bc
$ echo '0.4970436865354813*1.1' | bc -l
.54674805518902943
Hoặc bạn sẽ cần phải học cách sống với sự thiếu quyết đoán vốn có của phao.
Trong các dòng ban đầu của bạn có một số vấn đề:
- Hệ số 1,1 là tăng 10%, không phải 1% (nên là số nhân 1,01). Tôi sẽ sử dụng 10%.
Định dạng chuyển đổi từ một chuỗi thành một số (nổi) được đưa ra bởi CONVFMT. Giá trị mặc định của nó là %.6g
. Điều đó giới hạn các giá trị ở 6 chữ số thập phân (sau dấu chấm). Điều đó được áp dụng cho kết quả của sự thay đổi gsub của $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
Định dạng printf g
loại bỏ các số 0 ở cuối:
$ 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
Cả hai vấn đề có thể được giải quyết với:
$ echo "$a" | awk '{printf("%.17g\n", $1*1.1)}'
0.54674805518902947
Hoặc là
$ echo "$a" | awk -v CONVFMT=%.30g '{gsub($1, $1*1.1)}; {printf("%.17f\n", $1)}'
0.54674805518902947
Nhưng đừng hiểu rằng điều này có nghĩa là độ chính xác cao hơn. Các đại diện số nội bộ vẫn là một float trong kích thước gấp đôi. Điều đó có nghĩa là độ chính xác 53 bit và với điều đó bạn chỉ có thể chắc chắn 15 chữ số thập phân chính xác, ngay cả khi nhiều lần lên đến 17 chữ số trông chính xác. Đó là một ảo ảnh.
$ echo "$a" | awk -v CONVFMT=%.30g '{gsub($1, $1*1.1}; {printf("%.30f\n", $1)}'
0.546748055189029469325134868996
Giá trị đúng là:
$ echo "scale=18; 0.4970436865354813 * 1.1" | bc
.54674805518902943
Điều này cũng có thể được tính bằng awk (GNU) nếu thư viện bignum đã được biên dịch trong:
$ echo "$a" | awk -M -v PREC=100 -v CONVFMT=%.30g '{printf("%.30f\n", $1)}'
0.497043686535481300000000000000