Для більшої точності (GNU) awk (із складеним бінтумом) використовуйте:
$ 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