Haskell 高效地将字节打包为整数?
这是一个一开始似乎很简单的问题,但我已经研究了一段时间,找不到答案 我需要将字节列表(即--Haskell 高效地将字节打包为整数?,haskell,Haskell,这是一个一开始似乎很简单的问题,但我已经研究了一段时间,找不到答案 我需要将字节列表(即--Word8s)转换为任意长度的数字(即--整数)。比如说 intPack::[Word8]->Integer intPack [1] = 1 intPack [1, 0] = 256 showHex (intPack [1,2,3,4,5,6,7,8,9,10,11]) "" = "102030405060708090a0b" 缓慢的解决方案易于编写(请参见中的答案) ……但我畏缩于此,所有额外的
Word8
s)转换为任意长度的数字(即--整数
)。比如说
intPack::[Word8]->Integer
intPack [1] = 1
intPack [1, 0] = 256
showHex (intPack [1,2,3,4,5,6,7,8,9,10,11]) "" = "102030405060708090a0b"
缓慢的解决方案易于编写(请参见中的答案)
……但我畏缩于此,所有额外的乘法和加法,加上中间创建的一组无用的整数,只是为了(可能)得到与我填充到整数类型的内部结构中的相同字节。
当然,我不知道Integer如何存储数据的细节(也许它做的事情比在可变长度数组中保存字节更复杂……比如使用标志表示数字的长度,比如utf-8在编码字符时所做的)。至少应该知道上面的
intPack
已经非常好了。。。。然后我可以停止我的研究,咬紧牙关(或者更确切地说是字节:)继续前进。我会看看binary
包,它可以有效地打包和解包二进制数据结构:
一些想法:
二进制整数
实例是否适用于您:
import Data.Binary
import qualified Data.ByteString.Lazy.Char8 as LBS
main = do
let i = 0x0102030405060708090a0b0c0d0e0f :: Integer
bs = encode i
print ("before", i)
LBS.writeFile "output" bs
j <- fmap decode $ LBS.readFile "output" :: IO Integer
print ("after", j)
导入数据。二进制
将限定数据.ByteString.Lazy.Char8作为LBS导入
main=do
设i=0x0102030405060708090a0b0c0d0e0f::整数
bs=编码i
打印(“之前”,i)
LBS.writeFile“输出”bs
j我很想看到这个问题的一个好答案,但是如果您非常担心性能,您不应该使用ByteString
s而不是列表吗?另外,Haskell的Integer
类型是由GMP
库实现的。我想我应该看看GMP
是如何实现的。。。。实际上,我在实际问题中使用了ByteString,但在这里对问题进行了简化。任何sol'n都可以使用B.pack
,B.unpack
轻松转换,因此我认为这并不重要,但如果它真的重要,那么就让我们知道上面所有的[Word8]
实际上都是ByteString
s。提供了一些关于GMP
lib如何实现的信息,尽管我仍然不清楚是否可以使用这些信息。至少它似乎将值存储为字节,因此似乎仍然可以有效地执行此操作。我在其他地方使用过它,但它(似乎)仅适用于固定大小的值(8位、16位、32位、64位)。我需要任意长度。@jamshidh当然有一个Integer
的Binary
实例,但看看它似乎是基于与您已经想到的类似的折叠,虽然使用了效率更高的Data.Bits
函数,而不是加法和乘法。但关于固定大小的问题,我得到了纠正。。。。解码/编码将整数
转换为[Word8]
。我对此感到兴奋,直到我意识到它并不是在做一个简单的包,但是如果你看出来的[Word8]
,有时它是有效的(即-0x0102产生[0,0,0,1,2],如果你忽略填充),有时它完全失败(0x0102030405产生[1,1,0,0,0,0,0,0,0,0,5,4,3,2,1]!呃)。因为我正在离线读取数据,无法设置编码,所以我运气不好。
import Data.Binary
import qualified Data.ByteString.Lazy.Char8 as LBS
main = do
let i = 0x0102030405060708090a0b0c0d0e0f :: Integer
bs = encode i
print ("before", i)
LBS.writeFile "output" bs
j <- fmap decode $ LBS.readFile "output" :: IO Integer
print ("after", j)