如何在 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 位的乘积?