在Ruby中打包一个长二进制整数

时间:2011-11-20 08:06:46

标签: ruby pack

我正在尝试通过UDP发送一个非常长的二进制整数(大约200位)。当我尝试使用Array的pack方法时,它会抱怨我试图转换的字符串太大。

我是以错误的方式解决这个问题吗?

ruby-1.8.7-p352 :003 > [0b1101001010101101111010100101010011010101010110010101010101010010010101001010101010101011101010101010101111010101010101010101].pack('i')
RangeError: bignum too big to convert into `unsigned long'
from (irb):3:in `pack'
from (irb):3

这个数字应该代表DNS查询数据包(这是用于家庭作业;我们不允许使用任何DNS库。)

2 个答案:

答案 0 :(得分:4)

你需要将你的号码分成小块。最好的方法是一次编码32位:

> num = 0b1101001010101101111010100101010011010101010110010101010101010010010101001010101010101011101010101010101111010101010101010101
=> 17502556204775004286774747314501014869
> low_1 = num & 0xFFFFFFFF
=> 2864534869
> low_2 = (num >> 32) & 0xFFFFFFFF
=> 625650362
> low_3 = (num >> 64) & 0xFFFFFFFF
=> 1297454421
> low_4 = (num >> 96) & 0xFFFFFFFF
=> 220913317
> (low_4 << 96) + (low_3 << 64) + (low_2 << 32) + low_1
=> 17502556204775004286774747314501014869
> msg = [low_4, low_3, low_2, low_1].pack("NNNN")
=> "\r*\336\245MU\225U%J\252\272\252\275UU"
> msg.unpack("NNNN").inject {|sum, elem| (sum << 32) + elem}
=> 17502556204775004286774747314501014869

我更喜欢32位,因为您将它们打包在Network Byte Order中,这使得与其他平台的互动变得更加容易。 pack()方法不提供网络字节顺序64位整数。 (这并不太令人惊讶,因为POSIX不提供64位例程。)

答案 1 :(得分:-1)

Ruby 1.9.3正常工作。

irb(main):001:0> [0b1101001010101101111010100101010011010101010110010101010101010010010101001010101010101011101010101010101111010101010101010101].pack('i')
=> "UU\xBD\xAA"
相关问题