(product (take 9 [1000,999..])) `div` (product (map (\j-> product [1..j]) (map (\j->length(j)) (group [2,2,2,2,2,2,2,2,2]))))
以上代码的格式为X div
Y,X=product (take 9 [1000,999..])
& Y=(product (map (\j-> product [1..j]) (map (\j->length(j)) (group [2,2,2,2,2,2,2,2,2]))))
如果我将代码复制并粘贴到ghci中,它会给我-12740133310672
作为答案,
但是,如果我单独计算X & Y
,我会得到964541486381834014456320000 & 362880
,然后将它们除以2658017764500203964000
作为答案。
我认为这种不连贯可能是因为数字太大,但由于计算机可以单独正确地计算X和Y,为什么它不能将它们组合起来呢?
答案 0 :(得分:10)
Prelude Data.List> let x = product $ take 9 [1000,999..]
Prelude Data.List> x
964541486381834014456320000
Prelude Data.List> :t x
x :: (Enum a, Num a) => a
观察x
具有通用编号的类型:您只使用任何编号类型的操作来计算它。当您在GHCi中评估这样的数字时,它默认为“最安全”的具体类型,即Integer
,一种任意精度类型,对于大数字没有问题。但是,您可以使用任何其他数字类型强制执行计算:
Prelude Data.List> x :: Integer
964541486381834014456320000
Prelude Data.List> x :: Float
9.645414e26
Prelude Data.List> x :: Double
9.645414863818342e26
Prelude Data.List> x :: Int
-4623139575776374784
浮点版本不准确但仍然接近,而Int
(机器大小的固定精度数字)只是溢出并给出完全虚假。
通常这不会打扰你,因为默认使用安全Integer
类型进行大量计算。
也就是说,除非别的东西阻止了它。
Prelude Data.List> let y = product (map (\j-> product [1..j]) $ map length (group [2,2,2,2,2,2,2,2,2]))
Prelude Data.List> y
362880
Prelude Data.List> :t y
y :: Int
与x
不同,y
的类型已经具体:必须为Int
,因为这是length
的结果类型。 (理由是:一个如此大的列表,你无法用Int
测量它的长度,无论如何都无法适应内存。)
现在,div
与Haskell中的大多数数字函数一样,要求参数和结果具有相同的类型。因此,x`div`y
整体计算为Int
而不是Integer
,包括x
。正如我们所见,将x
计算为Int
会导致伪造。
OTOH,如果您使用362880
作为文字,那么这与length
无关。它只是一个通用数字,如x
,因此GHCi将再次默认为安全Integer
,即你得到
Prelude Data.List> x `div` 362880
2658017764500203964000
如果您只允许y
的转换,则可以获得相同的结果:
Prelude Data.List> x `div` fromIntegral y
2658017764500203964000
答案 1 :(得分:0)
使用Integer而不是Int有助于:
let r :: Integer ; r = (product (take 9 [1000,999..])) `div` (product (map (\j-> product [1..j]) (map (\j->fromIntegral $ length(j)) (group [2,2,2,2,2,2,2,2,2]))))
得到我:2658017764500203964000
我不完全理解你的代码,但我认为如果你单独计算它们会得到较小的中间结果 - 所以Int不会溢出。
所以是的 - 不连贯是因为数字很大(Int的宽度有限,所以它只会溢出(负数)。如果你使用如此大的数字操作,你应该使用Integer,它有无限宽度。