(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]))))
Run Code Online (Sandbox Code Playgroud)
上面的代码格式为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,为什么它不能将它们组合起来呢?
lef*_*out 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
Run Code Online (Sandbox Code Playgroud)
观察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
Run Code Online (Sandbox Code Playgroud)
浮点版本不准确但仍然接近,而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
Run Code Online (Sandbox Code Playgroud)
不同的是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
Run Code Online (Sandbox Code Playgroud)
如果您只允许转换,则可以获得相同的结果y
:
Prelude Data.List> x `div` fromIntegral y
2658017764500203964000
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
220 次 |
最近记录: |