twosumアルゴリズムの研究
from pint import roundfloat as rf
from pint import roundmode as rdm
a=0.1
b=0.2
誤差が発生するパターン
rf.rdadd(a, b, rdm.nearest)
0.30000000000000004
最近点丸め
rf.rdadd(a, b, rdm.up)
0.30000000000000004
上方向丸め。最近点丸めと一緒なので、最近点丸めでは上方向に丸め込まれた
rf.rdadd(a, b, rdm.down)
0.3
下方向丸め。最近点丸めと別方向に曲がったことがわかる
rf.twosum(a, b)
(0.30000000000000004, -2.7755575615628914e-17)
twosumを実行してみると、最近点丸めの際の、真値(2進数表現できない)との誤差の方向が検出できているのがわかる。
詳しく見ていこう
x = a + b
print(x)
0.30000000000000004
普通の足し算だ
tmp = x - b
print(tmp)
0.10000000000000003
tmp = x - b = (a + b) - b = a
であるのでこれはaとなるはずである。
だが、ならない
xは最近点丸めで計算されているため、bを引き算したときに、aに誤差sが加算されている。
tmp = a + 誤差s という形になっている
y = a - tmp
print(y)
-2.7755575615628914e-17
y = a - tmp = a - (a + 誤差s) = 誤差s という式になっている