背景
0に非常に近い実数値は、指数関数表現で問題なく表される。
一方、確率など扱う場合など、1に非常に近い値も扱うこともあるが、その場合、丸められてしまう。
例えば、
irb> 1.0-0.0000000000000001
=> 1.0
など。その場合、1-xのxだけを計算すればよいのだが、対数(log)を計算した時がある。
そんなとき、そのまま入れても、
irb> Math.log(1.0-0.00000000000000001)
=> 0.0
となってしまう。
近似値
xが非常に小さい時、log(1-x)の近似値は、-xである。
irb> x=-0.000000001
=> -1.0e-09
irb> Math.log(1.0-x)
=> 1.00000008224037e-09
(ざっくりとした)理由
log(1-x)の微分(傾き)は-1/xである。xが1のとき、log(1-x)の微分は、-1となる。すなわちこれは、同じく-1となる-xと同じと思って良い(ただしxが1に非常に近い時のみだが)。
どっかでみたような…
はいはい、自分も書きながらどこかでこんな話があったことを思い出した。
そんな人は「対数のテイラー展開」で検索するべし。
追記
2014/07/09: log1p関数
phpやjavaでは、
log1pという名前の関数があるみたい。rubyではないようなので実装してみた。
def log1p(x)
x.abs < 0.00001 ? x : Math.log(1+x)
end
</pre>
え?ざっくりしすぎ?
golang のソース(のコメント欄にある近似式)があったので、実装してみた。
def log1p(x)
u = 1+x
(u==1.0) ? x : Math.log(u)*(x/(u-1.0))
end