LoginSignup
0
0

More than 1 year has passed since last update.

Python Language - format() built-in Floating Point Rounding(浮動小数点数の端数処理 - 丸め)

Last updated at Posted at 2022-11-30

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.1151.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 で偶数丸めに合致していることが分かります。

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0