问题描述
这是我的 Haskell 函数,用于从列表中删除 2::Int
和 5::Int
:
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,23] == [23]
True
λ> product (remPrimesFactors25 [2,23])
23
λ> product [23]
23
λ> product (remPrimesFactors25 [2,23]) == product [23]
True
这是我的问题。为什么会发生这种情况?
λ> mod (10^22) (product (remPrimesFactors25 [2,23]) )
15
λ> mod (10^22) (product [23])
1
解决方法
remPrimesFactors
总是返回 Int
值的列表,而不是 Integer
值。由于 mod
要求两个参数具有相同的类型,因此 10^22
也被视为 Int
,它没有处理大数的精度准确。
Prelude> 10^22 :: Integer
10000000000000000000000
Prelude> 10^22 :: Int
1864712049423024128
,
您正在使用 Int
。 Int
使用固定数量的位,并且至少可以表示 -229 到 229-1 范围内的所有值。通常在 32 位机器上,它的范围是 -231 到 231-1,在 64 位机器上 -263 到 263-1。 10^22
然而大于这些范围。这意味着 10^22
的 Int
将在 64 位机器上表示为例如 1'864'712'049'423'024'128。
如果你使用一个Integer
,它可以代表任意大小的值,那么就不存在这个问题了。如果您因此将函数重写为:
remPrimesFactors25 :: [Integer] -> [Integer]
remPrimesFactors25 = filter (\x -> x != 2 && x != 5)
然后 10^22
将被解释为 Integer
,因此 10^22
将取值为 10'000'000'000'000'000'000'000。
然而,您不需要计算 10^22
。您可以使用 powerMod :: (Integral a,Integral b) => a -> b -> a -> a
中的 arithmoi
package 之类的算法。