I use abs(-9223372036854775808) in Julia
but output is -9223372036854775808
Is this a bug?
No, this is an integer overflow problem because -9223372036854775808
is the minimum number representable as a 64-bit signed integer. That is, it is equal to typemin(Int64)
. The help for abs
calls this out:
help?> abs
search: abs abs2 abspath AbstractSet abstract type AbstractChar AbstractDict AbstractFloat AbstractArray
abs(x)
The absolute value of x.
When abs is applied to signed integers, overflow may occur, resulting in the return of a negative value.
This overflow occurs only when abs is applied to the minimum representable value of a signed integer. That
is, when x == typemin(typeof(x)), abs(x) == x < 0, not -x as might be expected.
julia> abs(-3)
3
julia> abs(1 + im)
1.4142135623730951
julia> abs(typemin(Int64))
-9223372036854775808
If you are dealing with integers of this magnitude then you should use BigInts:
julia> abs(big"-9223372036854775808")
9223372036854775808
This is a consequence of two’s complement arithmetic, but possibly it should throw an InexactError
.
In general, though, we don’t check for overflow in integer arithmetic for performance reasons:
julia> Int8(127) + Int8(1)
-128
julia> -Int8(-128)
-128
so it makes sense that abs
is no different. If you are doing integer arithmetic that runs into this, you should generally use a larger integer type. If your numbers are so large that you are overflowing 64-bit integers, then you are probably doing some type of number theory or combinatorics (rather than counting real things like bytes or loop iterations) and you should use BigInt
.
This actually seems inaccurate, because the very same phenomenon occurs with minus as with abs
:
julia> x = typemin(Int)
-9223372036854775808
julia> -x
-9223372036854775808
julia> abs(x) == -x == x
true
Yes, another overflow: x == typemin(T) == typemax(T) + one(T) == -x
for any machine integer type. It depends if you read -x
in those docs as meaning a machine operation on a machine integer or a mathematical operation on a mathematical integer—could probably be clarified!
Just in case you can be sure your numbers would always fit in 128 bits, then Int128
will be much faster and take much less memory than BigInt
.
IMO it would be best if these functions continued to refrain from overflow checks. A situation where some operations (eg abs
) check, but others (eg +
, -
, ^
, …) don’t, is not really useful in practice. Alternatives exist, eg SaferIntegers.jl checks for this.