Haskell整数;到底发生了什么?

时间:2016-02-17 18:23:53

标签: haskell biginteger

最近对Haskell感到好奇,我开始做一些阅读。 Integer让我大吃一惊。

当我们说Integer可以任意大时,这是否意味着我的意思(即Integer的大小不受操作系统地址宽度的限制)?< / p>

假设我有足够的RAM可用于存储具有十亿个值的数字。 Haskell能够使用这个数字吗?

任何人都可以向我描述一下这是怎么回事?

2 个答案:

答案 0 :(得分:5)

  

假设我有足够的RAM可用于存储具有十亿个值的数字。 Haskell能够使用这个数字吗?

Prelude> length . show $ 10^1000000000
1000000001

当然,它确实占用了相当多的内存

enter image description here

但是如果你考虑一下 - 一个字节实际上可以存储高达256> 100的数字,即你可以在每个字节中存储两个以上的十进制数字。因此,具有十亿个数字的数字应该少于500 MB来存储......好吧,显然这里有一些开销需要乘法(当我show时,数字I生成一个低效列表-string)但没什么戏剧性的。

顺便说一句,它不是进行这些计算的Haskell / GHC,而是GHC使用的GMP

但是可以在Haskell中自己轻松实现这样的类型。例如。为简单起见,建议使用

的十进制数字列表
newtype DecDigit = DD { getDecDig :: Int }

instance Num [DecDigit] where
  fromInteger n | n < 10     = [DD $ fromInteger n]
                | otherwise  = let (cs,ls) = n`divMod`10
                               in DD $ fromInteger ls : fromInteger cs
  n + [] = n
  [] + n = n
  (DD n₀ : n) + (DD m₀ : m)
     | s₀<10      = DD s₀ : n+m
     | otherwise  = DD (s₀-10) : n+m+[DD 1]
   where s₀ = n₀+m₀

  ...

乘法有点困难,但基本上,就像罗伯特哈维所说,它都像你用笔和纸计算。

这是非常低效的!实际实现不使用十进制数字,而是充分利用机器大小的单词(可能使用现代处理器的128位甚至256位基本操作)。

答案 1 :(得分:4)

Haskell的Integer类型通俗地称为bignum类型。它的工作方式与手动执行数学计算的方式大致相同:处理数字而不是固定精度二进制字。

Bignum库通常将数字存储为数字集合。算术的工作方式与手动执行相同;通过操纵数字。