Clojure integer overflow

clojure, jvm

Solution

That's strange, I see different results with Clojure 1.4.0and Java(TM) SE Runtime Environment (build 1.7.0_06-b24), on Ubuntu 12.04 64bit:

user=> *clojure-version*
{:major 1, :minor 4, :incremental 0, :qualifier nil}
user=> (+ Integer/MAX_VALUE Integer/MAX_VALUE)
4294967294
user=> (type 1)
java.lang.Long
user=> (def max-plus-one (+ Integer/MAX_VALUE one))
#'user/max-plus-one
user=> max-plus-one
2147483648
user=> (type max-plus-one)
java.lang.Long
user=> (+ Integer/MAX_VALUE Integer/MAX_VALUE)
4294967294

You can always check the Java classes which clojure.core uses for numerics, to see how the functionality is implemented:

The implementation of the + operator in:

(defn +
  "Returns the sum of nums. (+) returns 0. Does not auto-promote
  longs, will throw on overflow. See also: +'"
  {:inline (nary-inline 'add 'unchecked_add)
   :inline-arities >1?
   :added "1.2"}
  ([] 0)
  ([x] (cast Number x))
  ([x y] (. clojure.lang.Numbers (add x y)))
  ([x y & more]
     (reduce1 + (+ x y) more)))

Java implementation of adding longs:

final public Number add(Number x, Number y){
    return num(Numbers.add(x.longValue(),y.longValue()));
}

Edits: Tested with Clojure 1.2.1 I have done a quick test with Clojure 1.2.1, and with that version of Clojure I get exactly your behavior.

user=> *clojure-version*
{:major 1, :minor 2, :incremental 1, :qualifier ""}
user=> (def one 1)
#'user/one
user=> (class 1)
java.lang.Integer
user=> (def max-plus-one (+ Integer/MAX_VALUE one))
#'user/max-plus-one
user=> max-plus-one
2147483648
user=> (class max-plus-one)
java.lang.Long
user=> (+ Integer/MAX_VALUE Integer/MAX_VALUE)
java.lang.ArithmeticException: integer overflow (NO_SOURCE_FILE:0)

I'd say that you did the test with Clojure 1.2.x, and not with 1.4.0. What is the value of *clojure-version* in your REPL?

Problem

I'm running Clojure 1.4.0. Why is it if I add `Integer/MAX_VALUE` and 1, I get a Long, but if I add `Integer/MAX_VALUE` to itself, I get an exception? ``` => (def one 1) => (class one) java.lang.Integer => (def max-plus-one (+ Integer/MAX_VALUE one)) => max-plus-one 2147483648 => (class max-plus-one) java.lang.Long => (+ Integer/MAX_VALUE Integer/MAX_VALUE) java.lang.ArithmeticException: integer overflow (NO_SOURCE_FILE:0) ``` Shouldn't they both act the same way? Why does adding two `MAX_VALUE` values overflows but adding 1 doesn't? I've seen this SO question but they are getting different behaviour than I am.

Original source

Related problems