24

It seems to happen all the time. For example:

(apply * (range 1 101))

gives me the error

ArithmeticException integer overflow  clojure.lang.Numbers.throwIntOverflow (Numbers.java:1374)

While in Ruby 1.9.2 the (conceptually) equivalent code,

(1..100).reduce(:*)

produces the desired result of

93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

Obviously the two languages are quite different under the hood but it seems like they should both be able to handle this calculation without issue. Am I doing something wrong here? Or do I have an incorrect understanding?

1
  • Which Clojure version you are using..? Wich Clojure 1.2.0, I got, 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000 Commented Jan 7, 2012 at 5:31

6 Answers 6

43

You need to use some form of BigInteger.

Try (apply *' (range 1 101)).

(see http://dev.clojure.org/display/doc/Documentation+for+1.3+Numerics -- evidently this auto-promotes upon overflow?)

Sign up to request clarification or add additional context in comments.

1 Comment

I accepted your answer but it seems like it didn't take. Let me know if it doesn't go through. Want to give credit where it's due!
8

From Clojure 1.3, you should cast Integer(or Long) to BigInt explicitly, otherwise there will be "ArithmeticException integer overflow" error when the number is too large.

There are three solutions, please pick the one you favor:

  • use one of the auto-promoting math functions:+', -', *', /', inc', dec'

    example: (apply *' (range 1 101))

  • use the BigInt type cast function

    example: (apply * (range (bigint 1) 101))

  • change to BigInt numeric literal

    example: (apply * (range 1N 101))

Reference: Documentation for Clojure 1.3 Numerics

Comments

6

Ruby has auto-promoting calculations, changing to a bigger bittype number when the result overflows its type. Because of performance considerations, calculations from Clojure 1.3 up will not be auto-promoting, and you need to take into account if a calculation can overflow, or use one of the auto-promoting math functions (+', -', *', /') if performance wouldn't be an issue.

Comments

1

in 1.3.0

(apply * (range 1N 101N));clojure.lang.BigInt

(apply * (range 1M 101M));java.math.BigDecimal

Comments

1

Stumbled onto the same situation. For me using "1.0" instead of "1" did the trick.

(apply * (range 1.0 1000))

As documented, there is a difference between floats and decimals.

Comments

0

I don't know Clojure, but it looks like it's using 32-bit or 64-bit integers to do the calculation. 32-bit signed integers have a maximum value of 2^31 - 1 (a bit over 2*10^9). 64-bit integers have a max value of 2^64 - 1 (a bit over 4*10^18). The value you got from Ruby is much higher than that.

Obviously Ruby is using some other number representation under the hood.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.