Reputation: 4292
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?
Upvotes: 24
Views: 10574
Reputation: 6956
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.
Upvotes: 6
Reputation: 1597
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
Upvotes: 8
Reputation: 68
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.
Upvotes: 1
Reputation: 40145
in 1.3.0
(apply * (range 1N 101N));clojure.lang.BigInt
(apply * (range 1M 101M));java.math.BigDecimal
Upvotes: 1
Reputation: 32576
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.
Upvotes: 0
Reputation: 1824
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?)
Upvotes: 43