0

I have a binary string that I need to convert to a hexadecimal string. I have this code that does it pretty well

binary = '0000010000000000000000000000000000000000000000000000000000000000'
binary.to_i(2).to_s(16)

This will normally work but in this situation, the first four zeros, representing the first hexadecimal place is left out. So instead of 0400000000000000 it is showing 400000000000000.

Now, I know i can loop through the binary string manually and convert 4 bits at a time, but is there a simpler way of getting to my wanted result of '0400000000000000'?

Would rjust(16,'0') be my ideal solution?

0

2 Answers 2

2

You should use string format for such complicated results.

"%016x" % binary.to_i(2)
# => "0400000000000000"
Sign up to request clarification or add additional context in comments.

4 Comments

That requires you to either know the resulting length or calculate it.
Can someone explain further on how this works? I'm not understanding how this makes 16 and the syntax is off to me.
@apeiros The question was not clear on that point. I interpreted that the length is fixed since the OP is considering rjust(16,'0'). I took the 16 from there.
@uptownhr Here are the Docs for String#% it formats an argument based on a string format pattern as defined in Kernel#sprintf. In this case the format is "016" pad with 16 0 (zeros) "x" Convert Argument as a hexadecimal number. All sprintf formats are preceded by "%"
1

You can use this:

binary = "0000010000000000000000000000000000000000000000000000000000000000"
[binary].pack("B*").unpack("H*").first
# => "0400000000000000"

binary.to_i(2) will convert the value to a number. A number does not know about leading zeros. pack("B*") will convert 8 bit each to a byte, giving you a binary encoded String. 8 x 0 is "\x00", a zero byte. So unlike the number, the string preserves the leading zeros. unpack("H*") then converts 4 bits each into their hex representation. See Array#pack and String#unpack for more information.

4 Comments

Note this does have problems - delete the zero on the right for instance, and it will not change the value, despite the hex representation now properly being "0200000000000000"
Whether that is a problem depends on uptownhr's use case. Due to the way it was asked, I assume that any input which is not a multiple of 8 bits is not valid.
True, worth explaining the match to use case in the answer. I would generally expect the binary leading zeroes to represent something of fixed length. Although for conversion to hex, only multiples of 4 bits are necessary, it would be unusual to want this code to handle e.g. 28 binary digits to 7 hex digits.
There is also unpack1 that returns the first extracted value, so you can omit the first call: ruby-doc.org/core-2.7.1/String.html#method-i-unpack1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.