如何在 ruby​​ 中解压缩大于 64 位的数字?

Posted

技术标签:

【中文标题】如何在 ruby​​ 中解压缩大于 64 位的数字?【英文标题】:How do I unpack a number larger than 64 bits in ruby? 【发布时间】:2013-06-09 21:18:37 【问题描述】:

假设我有一个大约 1000 字节长的任意字符串。 (我正在研究加密货币。)我怎样才能将它解压缩成 BigNum?我知道如何将它打包成 8 位数字或 32 位数字。

s='I am a grumpy potato'
s.unpack('C*')
[73, 32, 97, 109, 32, 97, 32, 103, 114, 117, 109, 112, 121, 32, 112, 111, 116, 97, 116, 111]
s.upack('L*')
=> [1835081801, 1730175264, 1886221682, 1869619321, 1869898100]

或者,有没有一种直接的方法可以将 8 位数字组合成一个 BigNum?我可能会解压缩成一个 8 位数的数组,然后将数组的每个元素乘以 8 的后续幂。但这似乎太复杂了,不是正确的方法。

编辑:将 BigNum 转回字符串的首选方法是什么?我不是说 to_s,我的意思是采用相同的字节模式并将其解释为字符串?

【问题讨论】:

【参考方案1】:

我认为您对如何处理它的预感是正确的。 Unpack 不处理 Bignums;它们在经典上相当棘手,特别是因为它们不适合标准的 64 位 int。

您可以通过以下方式手动“解包”它:

str.unpack("C*").reverse.each_with_index.inject(0) do |sum, (byte, index)|
  sum + byte * (256 ** index)
end

也就是说,反转字节列表(如果在大端系统上),迭代每个字节,并将其值乘以256^position。一旦值足够大,Ruby 的 BigNum 就会发挥作用,您可以毫不费力地将字节字符串转换为非常大的数字。

您也可以在 32 位(或 64 位,如果平台支持)整数块中执行相同操作:

INT32_MAX = 256 ** [1].pack("L*").size
INT64_MAX = 256 ** [1].pack("Q*").size

str.unpack("L*").reverse.each_with_index.inject(0) do |sum, (byte, index)|
  sum + byte * (INT32_MAX ** index)
end

str.unpack("Q*").reverse.each_with_index.inject(0) do |sum, (byte, index)|
  sum + byte * (INT64_MAX ** index)
end

【讨论】:

很公平。您的解释说要反转字符串,但我看不到您的代码反转字符串的位置。 我不小心把反面编辑了。哎呀。我会重新编辑它。:)【参考方案2】:

非常感谢https://***.com/a/17014450/204070。对我来说很棒。 答案可以简化为:

str.unpack("C*").inject(0) do |sum, (byte, index)|
  sum * 256 + byte
end

【讨论】:

以上是关于如何在 ruby​​ 中解压缩大于 64 位的数字?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 64 位 Perl 中解压缩(64 位)无符号长整数?

如果使用struct.pack(fmt,v1,v2,...)在python打包,如何在cpp中解压缩数字

如何在 MIPS 中将两个数字相乘,得到大于 32 位的乘积?

如何在 .NET 中解压缩使用 Lempel-Ziv Haruyasu 算法压缩的字节?

如何在 Perl 中解压缩双精度值?

如何从 Node.js 中的二进制字符串中解压缩数据?