printfはどのように半分を小数点第1位に四捨五入しますか?


11

printf私のシステムではprintf (GNU coreutils) 8.26、とにバンドルされているバージョンの2つの異なる実装をテストしてい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位までの丸めをテストすると、混乱が生じます。つまり、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

どちらの実装でも異なる方法で行われ、どちらにも明確なパターンはありません。これらの2つprintfのsは、半分を小数点第1位に四捨五入する方法を教えてください。

回答:


19

GNU printfが使用するのlong doubleに対し、zsh は通常doubleのsを使用します。(たとえば)1.45を2の累乗の和として表すことができないため、IEEE 754浮動小数点表現が機能し、最も近い近似が精度によって異なります。少し多い(80ビットの場合)または少ない(64ビットの場合)ので、ご覧のように切り上げまたは切り捨てられます。

相変わらず、人間レベルの正確な表現と丸めを気にする場合は、浮動小数点を使用しないでください。


1
x.25とx.75(適切に小さいxの場合)には、他とは異なり、正確なバイナリ表現があることに注意してください。
Toby Speight
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.