Convert a hexadecimal number (of any size) into a binary number.

Input
A POSITIVE hexadecimal number with a 0x in the beginning. A valid input will always match the following regex: 0x[0-9a-fA-F]+. If the input is not a valid hexadecimal number, that is, anything not matching this regex, the output should be 0.

Output
The hexadecimal converted to binary.

Winning
Original Code-Golf Rules, Lowest amount of bites (bytes).

Examples

IN: 0x12
OUT: 10010

IN: 0xFF
OUT: 11111111

IN: 0XFF
OUT: 0

IN: #0ac4
OUT: 0

IN: 0x00101011
OUT: 100000001000000010001

IN: 0x525600
OUT: 10100100101011000000000

IN: 0x58f70555118ec400
OUT: 101100011110111000001010101010100010001100011101100010000000000

IN: 0x6669795966AF3000
OUT: 110011001101001011110010101100101100110101011110011000000000000

IN: 0b018474
OUT: 0

IN: 9577383
OUT: 0

IN: -483355
OUT: 0

IN: -0xf9ad92
OUT: 0
  • 7
    When you say "If the input isn't a valid hexadecimal number", what types of things can it be? A number in a different base? A non-numeric object? Some object made to crash the program is evaluated, possibly in a non-catchable way? Really, I would have suggested avoiding input validation at all; it feels like a chameleon challenge. – xnor Apr 12 '17 at 3:15
  • 2
    Inferring rules from test cases is not OK and likely will get the challenge closed as unclear. Besides that, the examples aren't clear to me. "#0ac4" makes it seem like any extra character(s) can be included. – xnor Apr 12 '17 at 3:21
  • 1
    I'm still not clear after the edit what inputs are possible. Is #0ac4 still a valid test case? – xnor Apr 12 '17 at 3:45
  • 5
    Your second testcase doesn't match your regex (the X is uppercase). – Dada Apr 12 '17 at 8:05
  • 1
    Do we need to take care of leading zeroes? Can we output something like 00011010 – Cows quack Apr 12 '17 at 11:34

16 Answers 16

up vote 2 down vote accepted

Pyth, 15 bytes

.B&qr0<z2"0x"vz

Explanation:

             vz  Evaluate the input as a literal, to get a number (casts to integer for hexadecimal input)
      <z2        Select the first two characters of (string) input
    r0           cast to lowercase (0X -> 0x)
   q     "0x"    check whether the text starts with "0x" or "0X" (negative numbers don't) 
  &              If it does, return the casted number
.B               and convert to binary string

Test Suite

With a rules clarification (that 0x must be lowercase) in the OP, you can remove r0 for 13 bytes.

.B&q<z2"0x"vz

Python 2, 67 62 60 59 bytes

n=input()
try:print bin(int(n,n[1]<'x'))[2:]
except:print 0

Try it online!

Version that errors on invalid input (27 bytes):

lambda n:bin(int(n,16))[2:]

Try it online!

05AB1E, 11 bytes

Î2£„0xQi¹Hb

Try it online!

Explanation

Î             # initialize stack with 0 and push input
 2£           # get the first 2 chars of input
   „0xQ       # compare to "0x"
       i      # if equal
        ¹H    # convert input from base-16 to base-10
          b   # convert to binary
  • Doesn't work with the test case 0XFF. – Okx Apr 12 '17 at 9:15
  • @Okx: Both the regex and the input section of the question states that correct input starts with 0x so I'd say that specific test-case is wrong. – Emigna Apr 12 '17 at 9:17
  • 1
    Ah yeah, I didn't notice that. – Okx Apr 12 '17 at 9:18

Batch, 402 bytes

@echo off
set/ps=
set r=0
if not %s:~0,2%==0x goto g
if %s%==0x goto g
if %s:0=%==x goto g
set t=%s%
for %%h in (0 1 2 3 4 5 6 7 8 9 a b c d e f)do call set t=%%t:%%h=%%
if not %t%==x goto g
set s=%s:~2%
for %%h in (0.0000 1.0001 2.0010 3.0011 4.0100 5.0101 6.0110 7.0111 8.1000 9.1001 a.1010 b.1011 c.1100 d.1101 e.1110 f.1111)do call set s=%%s:%%~nh=%%~xh%%
set r=%s:.=%
:g
echo %r:*1=1%

Takes input on STDIN. 8 lines are then mostly wasted on input validation, so the interesting lines are line 11, which replaces each hex digit with its binary equivalent, but due to Batch limitations, with a leading ., line 12, which deletes all the .s, and line 14, which removes leading 0s. However this fails for inputs like 0x0 so I "invalidate" those which means 0 is output instead.

PHP, 66 65 63 bytes

<?=decbin(hexdec(preg_filter("#^0x([a-f\d]+$)#i","$1",$argn)));

run as pipe with -F.

Without the 0x, the worst problem would be that both hexdec and base_convert simply ignore characters that are not hex; but with it, there has to be an explicit validity check anyway.


45 bytes without the 0x:

<?=decbin(ctype_xdigit($argn)*hexdec($argn));
  • echo stristr($a=$argn,"0X")==$a?decbin(hexdec(ltrim($a,Xx0))):0; Is this a nice Alternative? It should working for the given testcases – Jörg Hülsermann Apr 12 '17 at 17:25
  • @JörgHülsermann: It´s a nice alternative, and it´s working for all given test cases, but it does not check the hex value for validity (see my comment on hexdec and base_convert). – Titus Apr 14 '17 at 9:22
  • I know and I think the question is a joke with the given testcases. – Jörg Hülsermann Apr 14 '17 at 10:51
  • 1
    echo decbin(hexdec(preg_filter("#^0x([a-f\d]+$)#i","$1",$argn))); – Christoph Apr 14 '17 at 21:29
  • -2 Bytes <?= istead of echo with -F option – Jörg Hülsermann Jun 13 '17 at 23:34

JavaScript (ES6), 109 108 bytes

Works for any input size.

s=>/1.*|0$/.exec((/^0x([\da-f]+)$/i.exec(s)||'_0')[1].replace(/./g,d=>(+`0x1${d}`).toString(2).slice(1)))[0]

Test cases

let f =

s=>/1.*|0$/.exec((/^0x([\da-f]+)$/i.exec(s)||'_0')[1].replace(/./g,d=>(+`0x1${d}`).toString(2).slice(1)))[0]

console.log(f('0x12'));               // OUT: 10010
console.log(f('0XFF'));               // OUT: 11111111
console.log(f('#0ac4'));              // OUT: 0
console.log(f('0x00101011'));         // OUT: 100000001000000010001
console.log(f('0x525600'));           // OUT: 10100100101011000000000
console.log(f('0x58f70555118ec400')); // OUT: 101100011110111000001010101010100010001100011101100010000000000
console.log(f('0x6669795966AF3000')); // OUT: 110011001101001011110010101100101100110101011110011000000000000
console.log(f('0b018474'));           // OUT: 0
console.log(f('9577383'));            // OUT: 0
console.log(f('-483355'));            // OUT: 0
console.log(f('-0xf9ad92'));          // OUT: 0

  • Hmm ... 2 experienced golfers submitting JS solutions more than twice as long as mine has me wondering if I've missed something in the challenge. – Shaggy Apr 12 '17 at 10:58
  • @Shaggy It all depends on the interpretation of the first line of the challenge. I took it for granted that 'of any size' was a definite requirement -- and so did Neil apparently. – Arnauld Apr 12 '17 at 11:04
  • @Shaggy Just to clarify for everyone: your approach works for up to 0x1fffffffffffff -- aka Number.MAX_SAFE_INTEGER -- and returns rounded results beyond that. By luck, the two large test cases are rounded correctly. – Arnauld Apr 12 '17 at 12:22
  • Huh, I didn't realise that @Shaggy's code worked by accident; I guess I should have counted the distance between the first and last 1 bits in the result. By the way, do you need the $ in the first regexp? – Neil Apr 12 '17 at 23:22
  • @Neil I don't think I can get rid of this $. The idea is to get the final zero if there's no 1 at all in the result. – Arnauld Apr 12 '17 at 23:43

REXX, 45 bytes

arg '0X' n
if n>'' then say x2b(n)
else say 0

Retina, 149 bytes

.
;$&
T`L`l
f
71
e
70
d
61
c
60
b
51
a
50
9
41
8
40
7
31
6
30
5
21
4
20
3
11
2
10
;(\d{4})
$1
;(\d{3})
0$1
;(\d\d)
00$1
;
000
^(?!0{7}x).*
0
0{7}x0*

(note the trailing newline)

Try it online!

Here is an alternate solution at the cost of 7 bytes: Try it!

perl, 25

(code 24 + 1 flag -n)

printf"%8b",/^0x/i?hex:0

JavaScript (ES6), 116 111 bytes

f=
s=>/^0x[\da-f]+$/i.test(s)?s.replace(/./g,c=>parseInt(4+c,36).toString(2).slice(-4)).replace(/0+10*(.)/,'$1'):0
<input oninput=o.textContent=f(this.value)><pre id=o>0

Not limited to 53 bits of precision. Edit: Saved 5 bytes by rewriting my digit conversion, which also reduces my language requirements to ES6.

  • You can reduce the length by 13 bytes by evaluating each character as the hex value. Try it Online – fəˈnɛtɪk Apr 20 '17 at 14:23
  • @fəˈnɛtɪk That doesn't solve the question as posed. – Neil Apr 20 '17 at 15:45
  • Here, I removed leading zeroes from from the first conversion Try it Online still 2 bytes shorter. – fəˈnɛtɪk Apr 20 '17 at 16:09
  • @fəˈnɛtɪk I combined it with Arnauld's answer and got it down to 103: Try it online! – Neil Apr 20 '17 at 16:18
  • @fəˈnɛtɪk Wait, that doesn't work for the fifth test case 0x00101011, sorry. – Neil Apr 20 '17 at 16:20

8086 machine code - 63 bytes

Works for any input up to 125 chars (the maximum command line length in DOS)

00000000  be 82 00 bf 3f 01 89 fa  ad 3d 30 78 75 24 ac 3c  |....?....=0xu$.<|
00000010  0d 74 22 2c 30 3c 09 76  08 24 df 2c 07 3c 0f 77  |.t",0<.v.$.,.<.w|
00000020  11 b1 04 c1 e0 0c d0 e4  0f 92 c0 0c 30 aa e2 f6  |............0...|
00000030  eb dc ba 3d 01 b0 24 aa  b4 09 cd 21 c3 30 24     |...=..$....!.0$|
0000003f

JavaScript (ES6), 53 52 49 50 52 45 bytes

(Non-competing as it doesn't handle inputs of any size; I just got lucky with the sample inputs)

f=

h=>+/^0x[\da-f]+$/i.test(h)&&(+h).toString(2)

console.log(f`0x12`);
console.log(f`0XFF`);
console.log(f`#0ac4`);
console.log(f`0x00101011`);
console.log(f`0x525600`);
console.log(f`0x58f70555118ec400`);
console.log(f`0x6669795966AF3000`);
console.log(f`0b018474`);
console.log(f`9577383`);
console.log(f`-483355`);
console.log(f`-0xf9ad92`);

CJam, 24 bytes

q2/("0x"={seu:~Gb2bo}&;0

Try it online!

Explanation

q      e# Read the input
2/     e# Split it into 2-length segments
(      e# Pull out the first segment
"0x"=  e# Check if it equals "0x"
{      e# If it does, run this block:
 s     e#  Join the segments back together
 eu    e#  Make the string uppercase
 :~    e#  Eval each character (A-K are 10-20)
 Gb    e#  Convert from base 16 to base 10
 2b    e#  Convert to base 2
 o     e#  Output the binary number
}&     e# (end of block)
;0     e# Delete the top stack element and push 0. If the block was run, nothing is left
       e# on the stack, so the program terminates with an error before pushing 0.

JavaScript (ES6), 107 characters

f=
b=>/0x[\da-f]+$/i.test(b)&&b.match(/[\da-f](?!x)/gi).map(x=>((+('0x1'+x)).toString(2)).slice(-4)).join('')||0

console.log(f('0x1f'))
console.log(f('0x6669795966AF3000'))

Perl 6, 35 bytes

{(m/^0x(.+)/&&:16(~$0)//0).base(2)}

Javascript, 63 bytes

f=
x=>0|/^0x[A-Fa-f0-9]+$/.test(x)&&Number.parseInt(x).toString(2)

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.