Kevin
Kevin

Reputation: 745

Why does this complex rational give an overflow error in Julia?

When I want Julia (0.4.3) to compute (2.4 - 1.2im) // (0.7 - 0.6im), it gives an overflow error:

ERROR: OverflowError()
 in * at rational.jl:188
 in // at rational.jl:45
 in // at rational.jl:42

However (24 - 12 im) // (0.7 - 0.6im), mathmatically essentialy the same, does work. Also, (2.4 - 1.2im) / (0.7 - 0.6im) works too but this doesn't give a rational of course.

Is this a bug, or am I doing something wrong? Are there rationals that Julia can't work with?

Upvotes: 3

Views: 276

Answers (1)

Fengyang Wang
Fengyang Wang

Reputation: 12051

You should use:

(24//10 - 12im//10) / (7//10 - 6im//10)

instead.

Why does this happen? The numbers you write are floating point numbers—they are not 0.7 or 2.4, but rather approximations of those numbers. You can see this effect by converting to a Rational:

julia> Rational{Int64}(0.7)
3152519739159347//4503599627370496

The // operator used in your question did an implicit conversion to rationals, so results like these are observed.

Now why did an OverflowError occur? Because the type is Rational{Int64}, which means both numerator and denominator can only store numbers within the range of an Int64. Note what happens when we try to square this number, for instance:

julia> Rational{Int64}(0.7) * Rational{Int64}(0.7)
ERROR: OverflowError()
 in *(::Rational{Int64}, ::Rational{Int64}) at ./rational.jl:196
 in eval(::Module, ::Any) at ./boot.jl:234
 in macro expansion at ./REPL.jl:92 [inlined]
 in (::Base.REPL.##1#2{Base.REPL.REPLBackend})() at ./event.jl:46

The OverflowError tells us that the resulting rational is no longer exactly representable in this type, which is a good thing—after all, the whole point of Rational is to be exact! This could be fixed with Rational{BigInt}, but of course that comes with a substantial performance penalty.

So the root of the issue is that 0.7 and the like are floating point literals, and are therefore not exactly 0.7. Indeed, expressed exactly, 0.7 is 0.6999999999999999555910790149937383830547332763671875. Instead, using 7//10 avoids the issue.

Upvotes: 4

Related Questions