round関数はまだまだ議論があるようだ

普段そんなに計算機で小数とか扱わないので、たまに使って、結構上手くいかないもんだなと。そんで色々調べてたんですが。


以下Pythonの対話モード

>>> 0.1
0.10000000000000001
>>> 0.2
0.20000000000000001
>>> 0.3
0.29999999999999999

これは授業でもやったような話だね。

>>> 0.0007
0.00069999999999999999
>>> round(0.0007,4)
0.00069999999999999999

四捨五入して丸めたはずなのにそもそもぴったり表現できないから桁数多く見えちゃう。まあでもprintで表示すれば望みの桁までにはなります。

>>> print '% 04f' % 0.0007
0.0007
>>> print '% 0.5f' % 0.0007
0.00070



面白いな(いや、良く分かってないので、面白そうだな、が正しい)と思ったのは、以下のサイトの話。roundって結構まだどうしたらいいか決まって無い感じなんですね。

この人が継続的に議論しているようです。


違和感のある用例として面白いのはこんなのかな。

>>> round(0.49999999999999999)
1.0
>>> round(0.4999999999999999)
0.0


なお、Pythonには10進浮動小数点数モジュールというのがあるようです。

なんかあっさり達成されると、困惑してしまいます(笑)。

>>> import decimal
>>> decimal.Decimal(1)
Decimal("1")
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal("0.1428571428571428571428571429")
>>> decimal.getcontext().prec = 40
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal("0.1428571428571428571428571428571428571429")

>>> sum = decimal.Decimal(0)
>>> for n in range(10):
... sum += decimal.Decimal("0.1")

>>> sum
Decimal("1.0")


>>> sum2 = 0
>>> for n in range(10):
... sum2 += 0.1

>>> sum2
0.99999999999999989

イメージ通りに動きますね。小数点をdecimalにするには、数値を文字列で与えなきゃいけないようだ。