Reputation:
Here is my Haskell function to remove 2::Int
and 5::Int
from a list:
remPrimesFactors25 :: [Int] -> [Int]
remPrimesFactors25 [] = []
remPrimesFactors25 (x:xs)
| x == 2 = remPrimesFactors25 xs
| x == 5 = remPrimesFactors25 xs
| otherwise = x : remPrimesFactors25 xs
λ> remPrimesFactors25 [2,5,23]
[23]
λ> remPrimesFactors25 [2,5,23] == [23]
True
λ> product (remPrimesFactors25 [2,5,23])
23
λ> product [23]
23
λ> product (remPrimesFactors25 [2,5,23]) == product [23]
True
Here's my problem. Why does this happen?
λ> mod (10^22) (product (remPrimesFactors25 [2,5,23]) )
15
λ> mod (10^22) (product [23])
1
Upvotes: 2
Views: 102
Reputation: 476503
You are working with an Int
. An Int
uses a fixed number of bits, and can represent at least all values in the range of -229 to 229-1. Typically on 32-bit machine it will take the range of -231 to 231-1, and on a 64-bit machine -263 to 263-1. 10^22
however is greater than these ranges. This means that 10^22
for an Int
will be represented on a 64-bit machine for example as 1'864'712'049'423'024'128.
If you use an Integer
, which can represent values of arbitrary size, then there is no such problem. If you thus rewrite the function to:
remPrimesFactors25 :: [Integer] -> [Integer]
remPrimesFactors25 = filter (\x -> x != 2 && x != 5)
then 10^22
will be interpreted as an Integer
, and thus 10^22
will take as value 10'000'000'000'000'000'000'000.
You however do not need to calculate 10^22
. You can use algorithms like powerMod :: (Integral a, Integral b) => a -> b -> a -> a
of the arithmoi
package.
Upvotes: 2
Reputation: 530843
remPrimesFactors
always returns a list of Int
values, not Integer
values. Since mod
requires both arguments to have the same type, 10^22
is also treated as an Int
, which doesn't have the precision to handle the large number accurately.
Prelude> 10^22 :: Integer
10000000000000000000000
Prelude> 10^22 :: Int
1864712049423024128
Upvotes: 2