将四个8位无符号整数组合成一个32位无符号整数

时间:2014-12-12 04:41:40

标签: ruby bit-manipulation

给定一个包含四个8位无符号整数的数组,例如32-bit RGBA color

rgba = [255, 255, 255, 255] # white

将这四个Fixnums合并为一个32位Integer的最有效方法是什么?

目前,我正在使用pack and unpack:

rgba.pack('C*').unpack('L')[0] #=> 4294967295

# Check work: same value as corresponding hex literal
0xffffffff #=> 4294967295

但我想知道是否有更有效的方法。我发现了这个C ++问题:

Cleanest way to combine two shorts to an int

我认为<<是一个&#34;转移&#34;而|是一个&#34;掩码&#34;,但我对这些运营商了解不多,而且从未在红宝石中使用它们。

1 个答案:

答案 0 :(得分:2)

将每个元素移动 24 - (index * 8),然后将它们全部一起移动:

rgba = [255, 255, 255, 255]
rgba[0] << 24 | rgba[1] << 16 | rgba[2] << 8 | rgba[3]

我没有移动rgba[3]因为换零没有效果。

一些测量:

使用unpack

Benchmark.measure do
  100_000.times do
    rgba = [255, 255, 255, 255]
    rgba.pack('C*').unpack('L')[0]
  end
end

结果:

=> #<Benchmark::Tms:0x007fe137005350
 @cstime=0.0,
 @cutime=0.0,
 @label="",
 @real=0.146899,
 @stime=0.0,
 @total=0.1399999999999999,
 @utime=0.1399999999999999>

使用按位运算符

Benchmark.measure do
  100_100.times do
    rgba = [255, 255, 255, 255]
    rgba[0] << 24 | rgba[1] << 16 | rgba[2] << 8 | rgba[3]
  end
end

结果:

=> #<Benchmark::Tms:0x007fd66438fd28
 @cstime=0.0,
 @cutime=0.0,
 @label="",
 @real=0.088995,
 @stime=0.0,
 @total=0.08000000000000007,
 @utime=0.08000000000000007>