There are (at least) two types for whole numbers in Haskell: Integer
which can hold arbitrarily large numbers, but arithmetic is slower, and Int
, with a machine dependent maximal value and faster arithmetic (see also this question: Haskell Int and Integer)
Haskell's default integer type is Integer
, that's why there's no overflow in your haskell example. Scala's Int
(32 bit signed) however can overflow and then wraps around into negative numbers.
This is the reason for odd results as in factorial(50)=0
(and factorial(51) = factorial(52) = ... = 0
: Due to overflows, a temporary result in the multiplication is 0
, thus all following factorials are 0
as well.
Example using decimal numbers:
Let's assume that we are using a fixed width decimal representation with 3 places and only positive numbers (in reality, we would have 32 or 64 binary digits and Haskell and Scala both use signed numbers, but the basic concept stays the same):
- factorial 1 = 001
- factorial 2 = 002
- ...
- factorial 5 = 120
- factorial 6 = 720
- factorial 7 = 5040, BUT we can only store 3 digits, so this gets truncated to 040
- factorial 8 = (factorial 7) * 8 = 040 * 8 = 320
- factorial 9 = 320 * 9 = 2880 = 880
- factorial 10 = 880 * 10 = 8800 = 800
- factorial 11 = 800 * 11 = 8800 = 800
- factorial 12 = 800 * 12 = 9600 = 600
- ...
- factorial 15 = 200 * 15 = 3000 = 000
- factorial 16 = (factorial 15) * 16 = 000 * 16 = 000
- ...
An example on my 64 bit box, using Haskell:
Prelude> factorial 65 :: Int # largest nonzero factorial on my box
-9223372036854775808
Prelude> factorial 66 :: Int # all following factorials are zero
0
Prelude> -9223372036854775808 * 66 :: Int # because (factorial 65) * 66 = 0
0
Prelude> -9223372036854775808 * 66 # with arbitrary precision:
-608742554432415203328
Prelude> -608742554432415203328 / 2^64 # this happens to be a multiple of 2^64
-33.0
The same thing would happen with factorials in a fixed length base 10 representation: each factor that is a multiple of 10 introduces another 0 at the "right end of the number", so eventually, all digits of our imaginary fixed length base 10 integer are shifted out to the left.
With the internal binary representation used in Haskells or Scalas Int
, the same happens for each even factor, so that at some point, all bits are 0.