Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby: Why does unpack('Q') give a different result than manual conversion?

Tags:

ruby

unpack

I'm trying to write a function that will .unpack('Q') (unpack to uint64_t) without access to the unpack method.

When I manually convert from string to binary to uint64, I get a different result than .unpack('Q'):

Integer('abcdefgh'.unpack('B*').first, 2) # => 7017280452245743464

'abcdefgh'.unpack('Q').first # => 7523094288207667809

I don't understand what's happening here.

I also don't understand why the output of .unpack('Q') is fixed regardless of the size of the input. If I add a thousand characters after 'abcdefgh' and then unpack('Q') it, I still just get [7523094288207667809]?

like image 496
Adelmar Avatar asked Oct 20 '25 04:10

Adelmar


1 Answers

Byte order matters:

 Integer('abcdefgh'.
           each_char.
           flat_map { |c| c.unpack('B*') }.
           reverse.
           join, 2)
 #⇒ 7523094288207667809
 'abcdefgh'.unpack('Q*').first
 #⇒ 7523094288207667809

Your code produces the wrong result because after converting to binary, bytes should be reversed.


For the last part of your question, the reason the output of .unpack('Q') doesn't change with a longer input string is because the format is specifying a single 64-bit value so any characters after the first 8 are ignored. If you specified a format of Q2 and a 16 character string you'd decode 2 values:

> 'abcdefghihjklmno'.unpack('Q2')
=> [7523094288207667809, 8029475498074204265]

and again you'd find adding additional characters wouldn't change the result:

> 'abcdefghihjklmnofoofoo'.unpack('Q2')
=> [7523094288207667809, 8029475498074204265]

A format of Q* would return as many values as multiples of 64-bits were in the input:

> 'abcdefghihjklmnopqrstuvw'.unpack('Q*')
=> [7523094288207667809, 8029475498074204265, 8608196880778817904]
> 'abcdefghihjklmnopqrstuvwxyz'.unpack('Q*')
=> [7523094288207667809, 8029475498074204265, 8608196880778817904]
like image 191
Aleksei Matiushkin Avatar answered Oct 23 '25 02:10

Aleksei Matiushkin