northclimbの備忘録

徒然なるままに...です。

JuliaでRationalは危ないかも

repl.itでJulia(ver 1.3.1)を触って遊んでいたら、Rationalでとんでもないことになったので書いておく。分母でオーバーフローぎりぎりを扱う可能性のある人は気をつけて。

まず、適当に以下を実行してみてほしい。aは今回の挙動に関係ないので他の数でも問題ないと思う。

a = typemax(Int64)
b = typemin(Int64)

println("a = typemax(Int64) = $(a)")
println("b = typemin(Int64) = $(b)")
println("a // b = $(a//b)")
println("(a // b) * 2 = $((a // b) * 2)")

結果はこんな感じになるはず。

a = typemax(Int64) = 9223372036854775807

b = typemin(Int64) = -9223372036854775808

a // b = -9223372036854775807//-9223372036854775808

(a // b) * 2 = 9223372036854775807//4611686018427387904

見てわかると思うが、 (a//b)*2 は負になるはず。
Rational.jlを見た感じだと21行目のchecked_denで分母を正に直しているようだが、

>a = typemin(Int64)

-9223372036854775808

>-a

-9223372036854775808

からわかるように、 typemin(T<:Integer) に対して負の単項演算は機能しない。(当たり前だけど...)
たぶん、これが原因だろう。

以上、Rational使うと 0.1 * 3 とかを誤差なしで計算できるけど安心しすぎてはダメだよって話でした。


英語ですが、Juliaのドキュメントも読みましょう。


Juliaに関するおすすめの書籍はこちら

1から始める Juliaプログラミング

1から始める Juliaプログラミング