Ruby:为什么解压缩(' Q')会产生与手动转换不同的结果?

时间:2018-04-29 09:28:05

标签: ruby unpack

我试图编写一个函数.unpack('Q')(unpack to uint64_t),而无需访问unpack方法。

当我手动将字符串转换为二进制文件到uint64时,我得到的结果与.unpack('Q')不同:

Integer('abcdefgh'.unpack('B*').first, 2) # => 7017280452245743464

'abcdefgh'.unpack('Q').first # => 7523094288207667809

我不明白这里发生了什么。

我也不明白为什么无论输入的大小如何,.unpack('Q')的输出都是固定的。如果我在' abcdefgh'之后添加了一千个字符。然后解压缩(' Q')它,我仍然只是得到[7523094288207667809]

1 个答案:

答案 0 :(得分:2)

字节顺序很重要:

 Integer('abcdefgh'.
           each_char.
           flat_map { |c| c.unpack('B*') }.
           reverse.
           join, 2)
 #⇒ 7523094288207667809
 'abcdefgh'.unpack('Q*').first
 #⇒ 7523094288207667809

您的代码产生错误的结果,因为在转换为二进制文件bytes should be reversed

之后

对于问题的最后一部分,.unpack('Q')的输出不会因较长的输入字符串而改变的原因是因为格式指定了一个64位值,因此在第一个字符之后的任何字符8被忽略。如果您指定了Q2格式和16个字符的字符串,那么您需要解码2个值:

> 'abcdefghihjklmno'.unpack('Q2')
=> [7523094288207667809, 8029475498074204265]

并且您再次发现添加其他字符不会改变结果:

> 'abcdefghihjklmnofoofoo'.unpack('Q2')
=> [7523094288207667809, 8029475498074204265]

Q*格式将返回输入中的64位数的多个值:

> 'abcdefghihjklmnopqrstuvw'.unpack('Q*')
=> [7523094288207667809, 8029475498074204265, 8608196880778817904]
> 'abcdefghihjklmnopqrstuvwxyz'.unpack('Q*')
=> [7523094288207667809, 8029475498074204265, 8608196880778817904]