Ruby:为什么 unpack ('Q' ) 给出与手动转换不同的结果?

标签 ruby unpack

我正在尝试编写一个函数,它将 .unpack('Q')(解压到 uint64_t)而无需访问 unpack 方法。

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

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

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

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

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

最佳答案

字节顺序很重要:

 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]

关于Ruby:为什么 unpack ('Q' ) 给出与手动转换不同的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50085142/

相关文章:

php - 恢复解压 ('C*' , "string")

ruby - 从实例方法中获取 sinatra 环境

ruby-on-rails - 使用纯 Ruby 代码编写服务器应用程序是否明智?

python - 如何在 python 中将 16 位 PCM 数据转换为 float ?

python - 为什么将 struct.unpack 与 bytearray 一起使用的相同代码在 Python 2.7.3 中引发异常,但在 2.7.5 中却没有?

python - 解包到Python中的list append方法

ruby - 终止时杀死所有线程

ruby-on-rails - [GET] "/articles/new"中的路由错误 '

ruby-on-rails - 如果 checkin rails 表单标签

php - unpack(C*,data) Eats Memory [php 在 unpack 函数上耗尽内存]