Python では、他の多くの言語と同様に浮動小数点数における端数の丸めが行われます。
15. Floating Point Arithmetic: Issues and Limitations
https://docs.python.org/3.9/tutorial/floatingpoint.html
The Perils of Floating Point
https://www.lahey.com/float.htm
Python では IEEE 754 の Round to nearest, ties to even(最近接丸め(偶数)= 偶数丸め(= 銀行家の丸め =Bankers' Rounding ))
を採用しています。
IEEE 754
https://en.wikipedia.org/wiki/IEEE_754#Rounding_rules
※ decimal 等で丸めの方法を変更することも可能です。
Rounding modes
https://docs.python.org/3.9/library/decimal.html#rounding-modes
ここでは、典型的な丸めとして format() built-in の例をご紹介します。
format() built-in
https://docs.python.org/3.9/library/functions.html#format
環境
以下の Python 3.9 / Linux 環境で確認します。
$ uname -si
Linux x86_64
$ python3.9 -V
Python 3.9.13
$ python3.9
Python 3.9.13 (main, Jun 15 2022, 11:24:50)
[GCC 8.5.0 20210514 (Red Hat 8.5.0-13)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
float 型
以下のような float 型を使用します。
>>> for D in [(x / 1000 + 1.11) for x in range(1, 10)]:
... print(type(D), D)
...
<class 'float'> 1.111
<class 'float'> 1.112
<class 'float'> 1.113
<class 'float'> 1.114
<class 'float'> 1.115
<class 'float'> 1.116
<class 'float'> 1.117
<class 'float'> 1.118
<class 'float'> 1.119
この数字を format()
を使用して小数点第2位で丸めます。
>>> for D in [(x / 1000 + 1.11) for x in range(1, 10)]:
... print(type(D), D, "-> {:.2f}".format(D))
...
<class 'float'> 1.111 -> 1.11
<class 'float'> 1.112 -> 1.11
<class 'float'> 1.113 -> 1.11
<class 'float'> 1.114 -> 1.11
<class 'float'> 1.115 -> 1.11
<class 'float'> 1.116 -> 1.12
<class 'float'> 1.117 -> 1.12
<class 'float'> 1.118 -> 1.12
<class 'float'> 1.119 -> 1.12
偶数丸めにも関わらず、1.115
が 1.11
になっていることが分かります。
ここで、1.115
を [] 内に小数点20桁表示すると、実際の値は 1.11499999999999999112
であり、偶数丸めに合致していることが分かります。
>>> for D in [(x / 1000 + 1.11) for x in range(1, 10)]:
... print(type(D), D, "[{:.20f}]".format(D), "-> {:.2f}".format(D))
...
<class 'float'> 1.111 [1.11099999999999998757] -> 1.11
<class 'float'> 1.112 [1.11200000000000009948] -> 1.11
<class 'float'> 1.113 [1.11299999999999998934] -> 1.11
<class 'float'> 1.114 [1.11400000000000010125] -> 1.11
<class 'float'> 1.115 [1.11499999999999999112] -> 1.11
<class 'float'> 1.116 [1.11600000000000010303] -> 1.12
<class 'float'> 1.117 [1.11699999999999999289] -> 1.12
<class 'float'> 1.118 [1.11800000000000010481] -> 1.12
<class 'float'> 1.119 [1.11899999999999999467] -> 1.12
>>>
このようなケースが以下に記載されています。
15. Floating Point Arithmetic: Issues and Limitations
https://docs.python.org/3.9/tutorial/floatingpoint.html
上記を回避するために、Decimal() を使用してみます。
decimal — Decimal fixed point and floating point arithmetic
https://docs.python.org/3.9/library/decimal.html
>>> from decimal import Decimal
>>> for D in [Decimal(str(x / 1000 + 1.11)) for x in range(1, 10)]:
... print(type(D), D, "[{:.20f}]".format(D), "-> {:.2f}".format(D))
...
<class 'decimal.Decimal'> 1.111 [1.11100000000000000000] -> 1.11
<class 'decimal.Decimal'> 1.112 [1.11200000000000000000] -> 1.11
<class 'decimal.Decimal'> 1.113 [1.11300000000000000000] -> 1.11
<class 'decimal.Decimal'> 1.114 [1.11400000000000000000] -> 1.11
<class 'decimal.Decimal'> 1.115 [1.11500000000000000000] -> 1.12
<class 'decimal.Decimal'> 1.116 [1.11600000000000000000] -> 1.12
<class 'decimal.Decimal'> 1.117 [1.11700000000000000000] -> 1.12
<class 'decimal.Decimal'> 1.118 [1.11800000000000000000] -> 1.12
<class 'decimal.Decimal'> 1.119 [1.11900000000000000000] -> 1.12
1.115
の値は 1.115(小数点20桁表示では1.11500000000000000000)
となり、丸めの結果が 1.12
で偶数丸めに合致していることが分かります。