Concatenate four 8-bit unsigned ints into one 32-bit unsigned int

Given an array of four 8-bit unsigned integers, such as a 32-bit RGBA color

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

      

What's the most efficient way to combine these four Fixnums into one 32-bit Integer ?

I am currently using a package and unpacking:

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

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

      

but I'm wondering if there is a more efficient way. I found this question in C ++:

Cleanest way to combine two shorts into int

and I think that <<

is "shift" and a |

is "mask", but I don't know enough about these operators and have never used them in ruby.

+3


source to share


1 answer


Move each element by 24 - (index * 8), then OR all together:

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

      

I didn't shift rgba[3]

because offset by zero has no effect.

Some measurements:

Using unpack

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

      



Result:

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

      

Using bitwise operators

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

      

Result:

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

      

+2


source







All Articles