整数に丸める時の注意
Pythonだと
>>> round(1.5) 2.0 >>> round(2.5) 3.0 >>> round(3.5) 4.0 >>> round(4.5) 5.0
Rだと
> round(1.5) [1] 2 > round(2.5) [1] 2 > round(3.5) [1] 4 > round(4.5) [1] 4
round(偶数.5)
の結果は実装によって異なるらしい。端数処理 - Wikipediaによれば、整数に丸めるには少なくとも2つの方式があり、算数で習った「四捨五入」と、元の値に近い偶数側に丸める「最近接偶数への丸め」が含まれる。
四捨五入だと整数間のちょうど真ん中の数値であるX.5が常に正側に丸められることで、丸めた値の総和が下の値の総和よりずっと大きくなる一方で、最近接偶数への丸めはX(偶数).5の場合負側に丸められるため、全体としてバイアスが小さくなるという性質がある。従って、最近接偶数への丸めは、四捨五入よりも、丸めた値の総和が元の値の総和に近くなるため、金融分野や統計分野で好まれ、IEEE 754やISO/JISなどで標準の丸め方式として採用されている。
Cだと、round()
が四捨五入で、 rint()
が最近接偶数への丸めである。どのくらい差が出るものなのか、試してみた。
$ gcc -lm test_rint_round.c $ for i in $(jot 5); do ./a.out; sleep 1; done == result == sum(x) = 498305.00 sum(rint(x)) = 498296.00 (diff: -9.00) sum(round(x)) = 498805.00 (diff: 500.00) == result == sum(x) = 505284.00 sum(rint(x)) = 505292.00 (diff: 8.00) sum(round(x)) = 505784.00 (diff: 500.00) == result == sum(x) = 504254.00 sum(rint(x)) = 504260.00 (diff: 6.00) sum(round(x)) = 504754.00 (diff: 500.00) == result == sum(x) = 500216.00 sum(rint(x)) = 500226.00 (diff: 10.00) sum(round(x)) = 500716.00 (diff: 500.00) == result == sum(x) = 513174.00 sum(rint(x)) = 513164.00 (diff: -10.00) sum(round(x)) = 513674.00 (diff: 500.00)
多くの実装に、round()
という関数があるが、いつも四捨五入とは限らない。使う前に、また、説明する前に確認しておく癖を付けた方が良いだろう。