Question about abs()

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
1 Like

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.

3 Likes

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.

3 Likes