In Julia 1.7.2 multiplication of
3037000693 returns the negative product
-9223370870501072753. The product I expected is
function m(a::BigInt, b::BigInt)::BigInt
a * b
This function gives the same negative result.
Any ideas on how to get the correct answer in Julia 1.7.2 to
3037000691 * 3037000693 ?
I did run into this issue doing some math on (big) twin prime numbers.
julia> m(big(3037000691), big(3037000693))
Julia’s integers are machine integers with defined overflow behavior - the negative result is expected. Using
BigInt (like shown above by @jishnub) uses the GMP library in the background, which has arbitrary precision arithmetic which does not have overflow.
Do you have a runnable example where one of the two behaviors I described is not as expected?
Thanks for your answer. How should I (re)write the function to return the correct answer? I would like to use the arguments
3037000693 instead of
You can always explicitly convert if you know you always want the answer as a
function m(a, b)
big(a) * big(b)
The widen function can be used to generically convert to a wide enough type to store all possible arithmetic results. Ie
widen(a) * widen(b).
Without knowing anything more about your use case, except that you want to multiply two numbers, the only useful advice is to use
big or some other extended precision type.
Tell us more about what you need these numbers for, maybe we can give better input. Maybe you don’t actually need to multiply, or maybe you can divide them by something first.
Given Julia’s promotion rules, we could do “half the promotions” as we type:
big(a) * b
widen(a) * b
In fact it gives a MethodError, unless you supply Big arguments, as @jishnub shows.
widen(a) * b
That still fails for large numbers, depending on their types:
julia> a = 10^18
julia> b = Int128(10)^38
julia> widen(a) * b
julia> big(a) * b
Believe it or not the negative value is the correct (according to Int64 modular math), so expected by some.
Not it doesn’t:
julia> m(3037000691, 3037000693)
ERROR: MethodError: no method matching m(::Int64, ::Int64)
You probably also had such a function defined.
You additionally want:
julia> function m(a::Integer, b::Integer)
and maybe also (to not convert to big twice):
julia> function m(a::Int64, b::Int64)
big(widen(a) * widen(b))
You widened Int64, you should have widened Int128 in your example:
a * widen(b)