Multiplication of 2 positive numbers gives a negative product

In Julia 1.7.2 multiplication of 3037000691 and 3037000693 returns the negative product -9223370870501072753. The product I expected is 9223373203208478863.

function m(a::BigInt, b::BigInt)::BigInt
    a * b
end

This function gives the same negative result.

Any ideas on how to get the correct answer in Julia 1.7.2 to 3037000691 * 3037000693 ?

P.S.
I did run into this issue doing some math on (big) twin prime numbers.

julia> m(big(3037000691), big(3037000693))
9223373203208478863

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 037000691 and 3037000693 instead of big(037000691) and big(3037000693).

You can always explicitly convert if you know you always want the answer as a BigInt

function m(a, b)
    big(a) * big(b)
end
3 Likes

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).

8 Likes

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.

1 Like

Given Julia’s promotion rules, we could do “half the promotions” as we type:

big(a) * b
widen(a) * b
1 Like

In fact it gives a MethodError, unless you supply Big arguments, as @jishnub shows.

1 Like

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
-2659601278039724572920059057942822912

julia> big(a) * b
100000000000000000000000000000000000000000000000000000000
1 Like

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)
           m(big(a), big(b))
       end

and maybe also (to not convert to big twice):

julia> function m(a::Int64, b::Int64)
           big(widen(a) * widen(b))
       end

You widened Int64, you should have widened Int128 in your example:

a * widen(b) 
100000000000000000000000000000000000000000000000000000000