Python入門トップページ


目次

  1. プログラミング言語
  2. Anaconda - Jupyter Notebook / JupyterLab の環境設定
  3. Python の基礎
  4. リスト,タプル,辞書,集合
  5. 再び Jupyter Notebook の操作
  6. Python の制御構文
  7. 関数
  8. 便利な関数など
  9. リストの内包表記
  10. 多次元リスト
  11. クラス
  12. 演習問題
  13. 雑多な情報
    • 浮動小数点の取り扱い

Python の基礎

雑多な情報

浮動小数点の取り扱い

Python(だけでなく多くのプログラミング言語)では実数を浮動小数点 (float) の形式で取り扱います.例えば 0.5 という実数を格納した変数 afloat 型になっています(typeの説明はここを,?の説明はここを参照してください.).

a = 0.5
type(a)
float

?a
Type:        float
String form: 0.5
Docstring:   Convert a string or number to a floating point number, if possible.

10進数の 0.5 という値は \( 0.5 = 1 \times 2^{-1} = \frac{1}{2}\) と表すことができることから,2進数の浮動小数点で誤差なく表現することができます.なお,f文字列の説明はここを参照してください.

a = 0.5
print(f"{a:.40f}")
0.5000000000000000000000000000000000000000

\( 0.25 = 0 \times 2^{-1} + 1 \times 2^{-2} = \frac{1}{4}\)\( 0.125 = 0 \times 2^{-1} + 0 \times 2^{-2} + 1 \times 2^{-3} = \frac{1}{8}\) も同様に2進数の浮動小数点で誤差なく表現することができます.

a = 0.25
print(f"{a:.40f}")
a = 0.125
print(f"{a:.40f}")
0.2500000000000000000000000000000000000000
0.1250000000000000000000000000000000000000

さらに,\( 0.75 = 1 \times 2^{-1} + 1 \times 2^{-2} = \frac{1}{2} + \frac{1}{4}\)\( 0.625 = 1 \times 2^{-1} + 0 \times 2^{-2} + 1 \times 2^{-3} = \frac{1}{2} + \frac{1}{8}\) も同様です.

a = 0.75
print(f"{a:.40f}")
a = 0.625
print(f"{a:.40f}")
0.7500000000000000000000000000000000000000
0.6250000000000000000000000000000000000000

一方で,\( \frac{1}{3}\)0.333... という無限小数となって厳密に表現できないことと同様に,10進数の 0.1 は2進数の浮動小数点で無限小数となってしまいます.a = 0.1print で表示すると正確に表示されているように感じられます.

a = 0.1
print(f"{a}")
0.1

しかし,正確なのは先頭から16桁程度でそれ以降の桁は正しくありません.

a = 0.1
print(f"{a:.40f}")
0.1000000000000000055511151231257827021182

上の例や次の例のように,浮動小数点形式のデータを取り扱うときには,非常に小さな誤差が含まれるということに注意してください.

a = 0.2
print(f"{a:.40f}")
a = 0.3
print(f"{a:.40f}")
a = 0.33
print(f"{a:.40f}")
a = 0.01
print(f"{a:.40f}")
a = 0.001
print(f"{a:.40f}")
0.2000000000000000111022302462515654042363
0.2999999999999999888977697537484345957637
0.3300000000000000155431223447521915659308
0.0100000000000000002081668171172168513294
0.0010000000000000000208166817117216851329

なお,Pythonではメモリが許す限り大きな桁の整数を(誤差なく)扱うことができます

b = 123456789012345678901234567890
print(b)
123456789012345678901234567890

しかしながら,整数に 1.0 を掛けるという演算を行ったことで結果は浮動小数点の形式になり,その結果,有効桁が15桁程度になってしまうことにも注意してください.

b = 123456789012345678901234567890
c = b * 1.0
print(b)
print(c)
print(f"{c:.5f}")
123456789012345678901234567890
1.2345678901234568e+29
123456789012345677877719597056.00000

さらに,演算を繰り返すことで,その誤差は徐々に大きくなります.それでも有効桁が一気に小さくなることはないので,必要な有効桁が5桁や8桁程度であるならば恐れる必要もありません.次の例では,0.1 を 10回かけた後,10.0 を 10回かけています.さらにその操作を5回繰り返して,変数の値がどのように変化するか(数学的には一切変化しないはずですが)を確認しています.この場合,15桁目からの 5678 の箇所が,5713, 5783, 5836 のようになり,その誤差が徐々に大きくなっていますが,その一方で,15桁目までは変化することがなく,有効桁が15桁であることも確認できます.(この操作を何度か繰り返すと有効桁が14桁に減少することも確認すると良いでしょう.さらに繰り返したときに,有効桁が13桁,12桁・・・のようには減少しないことも同時に確認しましょう.)

b = 123456789012345678901234567890
print(b)
c = b * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 \
    * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0
print(f"{c:.5f}")
c = c * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 \
      * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0
print(f"{c:.5f}")
c = c * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 \
      * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0
print(f"{c:.5f}")
c = c * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 \
      * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0
print(f"{c:.5f}")
c = c * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 * 0.1 \
      * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0 * 10.0
print(f"{c:.5f}")
123456789012345678901234567890
123456789012345713062091685888.00000
123456789012345783430835863552.00000
123456789012345836207393996800.00000
123456789012345906576138174464.00000
123456789012345994537068396544.00000

目次に戻る