ntd*_*def 2 haskell types integer
只是为了踢,我想看看如果我在Haskell中定义一个函数会发生什么Int -> Int,知道它会溢出并且必须返回一个Integer.考虑以下:
factorial :: Int -> Int
factorial n = product [1..n]
Run Code Online (Sandbox Code Playgroud)
现在我知道如果我跑factorial 50,我会得到一个在'codomain'之外的数字factorial.由于Haskell是如此强类型,我希望它会返回一个错误.相反,GHCi返回一个奇怪的负面Int:
ghci> factorial 50
-3258495067890909184
Run Code Online (Sandbox Code Playgroud)
请注意
ghci> maxBound :: Int
9223372036854775808
Run Code Online (Sandbox Code Playgroud)
因为我在64位上运行.
我发现这种行为有点可怕:为什么Haskell没有引发错误?为什么factorial 50返回一个随机的负数?任何澄清将不胜感激.
ami*_*dfv 19
该Int类型定义为"至少具有[-2 ^ 29 ... 2 ^ 29-1]范围的固定精度整数类型." [0]范围因机器而异,但您可以使用minBound和找到它maxBound
它溢出的原因是它为它分配了固定数量的内存.想象一个更简单的例子 - 内存中的正整数,其最大值为7(在内存中存储为3位)
0表示为000,二进制
1表示为001
2表示为010等.
注意位数学是如何工作的:当你加1时,你要么把最小的数字从0变为1,要么把它从1变为0,并对下一个最重要的数字做同样的操作.
例如,011 + 1是100.
现在,如果你没有(就像Haskell所做的那样)在没有下一个最重要的数字的情况下执行此操作,那么它只会像往常一样增加,但是"会被切断".例如,111 + 1而000不是1000.这就是Haskell所发生的事情,除此之外其最低值(表示为一系列它使用其"最左边"位来表示+/-.你需要做到0s)是其最低负数.(maxBound :: Int) + (maxBound :: Int) + 20.
所以类似:
> maxBound :: Int
9223372036854775807
> (maxBound :: Int) + 1
-9223372036854775808
> (maxBound :: Int) + 2
-9223372036854775807
> let x = (maxBound :: Int) + 1 in x + x
0
Run Code Online (Sandbox Code Playgroud)
为什么"允许"这种情况发生?简单 - 效率.不检查是否存在整数溢出要快得多.这就是Integer存在的原因- 它是无限的,因为当你认为你可能会溢出,但你付出了效率的代价.
[0] http://www.haskell.org/ghc/docs/latest/html/libraries/base/Data-Int.html
| 归档时间: |
|
| 查看次数: |
2116 次 |
| 最近记录: |