Як друкуються круглі половинки до першого знаку після коми?


11

Я тестую дві різні реалізації printfв моїй системі: printf (GNU coreutils) 8.26і версію в комплекті zsh 5.3.1. Я тестую, як округлиться половина чисел, тобто для 1,5, 2,5, 3,5,… 9,5.

$ for i in {1..9}; do /usr/bin/printf '%.0f\n' "${i}.5"; done
2
2
4
4
6
6
8
8
10
$ for i in {1..9}; do printf '%.0f\n' "${i}.5"; done
2
2
4
4
6
6
8
8
10

Тут обидва чітко округлили половину до рівного . Однак, коли я тестую округлення до першого десяткового знака, речі стають заплутаними. Тобто я тестую на 1,15, 1,25, 1,35,… 1,95.

$ for i in {1..9}; do /usr/bin/printf '%.1f\n' "1.${i}5"; done
1.1
1.2
1.4
1.5
1.5
1.6
1.8
1.9
2.0
$ for i in {1..9}; do printf '%.1f\n' "1.${i}5"; done
1.1
1.2
1.4
1.4
1.6
1.6
1.8
1.9
1.9

Обидві реалізації роблять це по-різному, і я не бачу чіткого зразка в жодній. Як ці дві printfполовини круглих слів до першого десяткового місця?

Відповіді:


19

GNU printf використовує,long double а zsh використовує звичайні doubles . Поведінка округлення, яку ви бачите, полягає в тому, що (скажімо, 1.45) не може бути представлена ​​як сума потужностей 2, так працює IEEE 754 з плаваючою комою , і найближче наближення змінюється залежно від точності. Це трохи більше (з 80 бітами) або менше (з 64 бітами), таким чином округлюючи вгору або вниз, як бачите.

Як ніколи, якщо ви дбаєте про точне представлення на рівні людини та округлення, не використовуйте плаваючу крапку.


1
Лише зауважте, що x.25 і x.75 (для відповідно малих х) мають точні двійкові уявлення, на відміну від інших.
Toby Speight
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.