数値計算

はじめに

実計算に誤差はつきものである。 誤差にはいくつか種類があり、それは計算機に特有のものもあれば、そうでないものもある。 まず背景知識として、計算機での数値表現を説明する。 その後、数種類の誤差を紹介し、それぞれの例と対策を簡単に考える。 最後に誤差対策に使えそうな手法をいくつか紹介する。

計算機上での数値表現

int 型

http://www.kab-studio.biz/Programing/JavaA2Z/Word/00000249.html

固定小数点

http://www.kab-studio.biz/Programing/JavaA2Z/Word/00000148.html

float 型

https://www.cc.kyoto-su.ac.jp/~yamada/programming/float.html

http://www.kab-studio.biz/Programing/JavaA2Z/Word/00000097.html https://itmanabi.com/fixed-floating/

参考

http://www.kab-studio.biz/Programing/JavaA2Z/List/index.html

そもそもの誤差

測定誤差

例) 最小メモリが 1mm の定規 https://kotobank.jp/word/%E6%B8%AC%E5%AE%9A%E8%AA%A4%E5%B7%AE-1181095 https://www.keyence.co.jp/ss/measure/hakaritai/basic/errors/

有効数字も参考のこと http://dsl4.eee.u-ryukyu.ac.jp/DOCS/error/node6.html

離散化による誤差

音をデジタル化するときなどに発生する

http://www.mb.ccnw.ne.jp/kontoshi/papa/gimon/oto.htm http://www.kumikomi.net/archives/2010/07/ep22onse.php

float による誤差

丸め誤差

真の値を取ることが出来ない。 1/2 の乗数は、真の値を取れる。

s = 0
v = 0.1
for i in range(10):
    s += v
print(s) # 0.9999999

s = 0
v = 0.125 # 1/2 ** 3
for i in range(8):
    s += v
print(s) # 0.9999999

http://www.kab-studio.biz/Programing/JavaA2Z/Word/00000521.html

情報落ち誤差

大きな数と小さな数の加算による誤差

big = 10 ** 15 + 0.1
print(big) # debug
small = 0.1 ** 15
print(small) # debug
v = big - small
print(v) # debug
if v == big:
    print(True) # こっちに入る
else:
    print(False)

ALU は double より大きい bit 数で計算してたりするから、情報落ちしないこともある

//TODO 実際に試す
tmp = big + small;
res = tmp - big
res == 0 // tmp という変数に起こすと情報落ちするけど

res = big + small - big
res == small // 変数に起こさなければ、ALU が大きな bit を扱ってる場合は、情報落ちしないことがある

桁落ち誤差

近い値を持つ数の減算

x = 0.99999
y = 0.99998
print('x') # debug
print(x) # debug
print('y') # debug
print(y) # debug
print('x - y') # debug
print(x - y) # debug

a = 0.9
b = 0.8
print('a') # debug
print(a) # debug
print('b') # debug
print(b) # debug
print('a - b') # debug
print(a - b) # debug
print('0.1') # debug
print(0.1) # debug

その他の誤差

打ち切り誤差

漸化式を打ち切ることによる誤差 \sum 1/k2 = \pi ^2 / 6

その他の対策

分数 型 (有理数型) https://docs.python.org/ja/3/library/fractions.html

区間演算 https://ja.wikipedia.org/wiki/%E5%8C%BA%E9%96%93%E6%BC%94%E7%AE%97