Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 高效地将字节打包为整数?_Haskell - Fatal编程技术网

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)