【发布时间】:2013-02-09 10:18:02
【问题描述】:
我需要以一种与 Java 对 BigInteger 类所做的兼容的方式读写整数:
返回一个包含二进制补码表示的字节数组 这个大整数。字节数组将采用大端字节序: 最高有效字节在第零个元素中。该数组将包含 表示此 BigInteger 所需的最小字节数, 包括至少一个符号位,即 (ceil((this.bitLength() + 1)/8))。
遗憾的是,这排除了Data.Binary 提供的内容。在图书馆的某个地方遵循这个约定,有没有什么有效的方法可以有效地进行ByteString Integer 转换?如果没有,怎么办?
根据 Thomas M. DuBuisson 的回答(以及以下讨论),我目前有
i2bs :: Integer -> B.ByteString
i2bs x
| x == 0 = B.singleton 0
| x < 0 = i2bs $ 2 ^ (8 * bytes) + x
| otherwise = B.reverse $ B.unfoldr go x
where
bytes = (integerLogBase 2 (abs x) + 1) `quot` 8 + 1
go i = if i == 0 then Nothing
else Just (fromIntegral i, i `shiftR` 8)
integerLogBase :: Integer -> Integer -> Int
integerLogBase b i =
if i < b then
0
else
-- Try squaring the base first to cut down the number of divisions.
let l = 2 * integerLogBase (b*b) i
doDiv :: Integer -> Int -> Int
doDiv i l = if i < b then l else doDiv (i `div` b) (l+1)
in doDiv (i `div` (b^l)) l
这比我希望的更冗长,仍然错过了bs2i 函数。
【问题讨论】:
-
它必须是可移植的,还是你可以假设带有
integer-gmp包的GHC? -
我更喜欢便携式解决方案。如果我没记错的话,即使是 GHC 也可以在没有 GMP 的情况下构建?那样就有点太脆弱了。
-
是的,可以用
integer-simple构建。如果您使用内部组件,您可能会更有效率。还有一个问题,你想要一个只包含数字位的ByteString,还是让它成为更大的ByteString的一部分,以便你有一个字段来指定有多少字节组成表示?跨度> -
只需要原始位。
标签: haskell binary integer twos-complement