数値解析日記

数値解析関係のネタ帳。C++,pythonなど

JuliaのFloatとRoundingの奇妙な挙動[追記]

JuliaのFloatとRoundingの奇妙な挙動

with_rounding(Float64, RoundNearest) do
    exp(-0.999)
end
0.36824750461366296
with_rounding(Float64, RoundUp) do
    exp(-0.999)
end
0.3682475046136629
with_rounding(Float64, RoundDown) do
    exp(-0.999)
end
0.3682475046136629

本来、 Down <= Nearest <= Upとならなければならないところが
見た目上は Up < Nearest となってしまっている。


追記: Up <= Nearest を確認してみると成立しているため、計算上の問題はない 。表記がおかしいだけで、内部的には影響は小さいようだ


もちろん、Roundingは四則演算と平方根のみなのだが、結果が逆になったのは興味深い。
JuliaのRoundingのドキュメントを参照すると

Waring

Rounding is generally only correct for basic arithmetic functions (+(), -(), *(), /() and sqrt()) and type conversion operations. Many other functions assume the default RoundNearest mode is set, and can give erroneous results when operating under other rounding modes.

とあるので、expはおかしくなってしまったんだろう。issueをさらに調べると
exp(1) != e #3370  

Since exp(1) just calls openlibm's exp function, this appears to be an openlibm issue.

とあるので、openlibm側の問題のようだ。
当たり前だがexpにはRoundingは効かず、場合によっては妙な挙動を起こすことがわかる。
なお、これは利用者側が気をつけなければならない仕様であるので、Julia側に落ち度はない。
with_roundingやset_rounding内では、四則演算と平方根以外は利用しないほうが良いだろう。
(できれば、四則演算と平方根以外は最近点丸めで計算してくれるとありがたいんだけど…… )

なお、mpfrを利用するBigFloatではこのような問題は起こらない

with_rounding(BigFloat, RoundNearest) do
    exp(BigFloat(-0.999))
end
3.682475046136629215368118018604961977815208270355409127685022306741116356975955e-01
with_rounding(BigFloat, RoundUp) do
    exp(BigFloat(-0.999))
end
3.682475046136629215368118018604961977815208270355409127685022306741116356975998e-01
with_rounding(BigFloat, RoundDown) do
    exp(BigFloat(-0.999))
end
3.682475046136629215368118018604961977815208270355409127685022306741116356975955e-01

見づらいんで、大小比較すると

with_rounding(BigFloat, RoundNearest) do
    global near
    near = exp(BigFloat(-0.999))
end

with_rounding(BigFloat, RoundUp) do
    global up
    up = exp(BigFloat(-0.999))
end

with_rounding(BigFloat, RoundDown) do
    global down
    down = exp(BigFloat(-0.999))
end
3.682475046136629215368118018604961977815208270355409127685022306741116356975955e-01
down <= near <= up
true

となるのでmpfr上では大丈夫
なお、この現象はJulia 0.4.5で確認し、windows 10(64bit)、OS X 10.11.5で確認した