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

Input
A POSITIVE binary number with just the 0s and 1s. A valid input will always match the following regex: [0-1]+. If the input is not a valid binary number, that is, anything not matching this regex, the output should be 0 or the program should exit, or error. The output does not need the leading 0x nor does it need to be capitalized.

Output
The binary number converted to hexadecimal.

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

Examples

IN: [101]
OUT: [0x5] OR [5]

IN: [10000000010100100000]
OUT: [0x80520] OR [80520]

IN: [1010101]
OUT: [0x55] OR [55]

IN: [1111111111111111]
OUT: [0xFFFF] OR [FFFF] OR [0xffff] OR [ffff]

IN: [1012101]
OUT: [0]

IN: [a]
OUT: [0]

IN: [-1010101]
OUT: [0]

IN: [abcdef]
OUT: [0]

IN: [2]
OUT: [0]
  • 12
    Boo-urns to input validation! – Shaggy Aug 27 '17 at 20:19
  • 2
    Can we exit if the input isn't valid binary? – caird coinheringaahing Aug 27 '17 at 20:20
  • 6
    @DirtyDev Popularity contest would NOT better. – Level River St Aug 27 '17 at 21:29
  • 11
    You could shave one byte off your regex: [01]+ – martin Aug 28 '17 at 2:10
  • 7
    5 hours was far too quick to an accept a solution, especially one that does not meet the specs on invalid input. – Shaggy Aug 28 '17 at 9:32

28 Answers 28

MY, 8 6 5 bytes

⍞PrH↵

Try it online!

How?

  • line of raw input
  • P basify
  • r convert from binary
  • H convert to hex
  • output

Errors if input isn't correct.

Java, 126 119 117 110 104 Bytes

Thanks to Jakob and Zacharý

class A{public static void main(String[]s){System.out.print(Long.toHexString(Long.parseLong(s[0],2)));}}

Expanded:

class A
{
    public static void main(String[] s)
    {
        System.out.print(Long.toHexString(Long.parseLong(s[0], 2)));
    }
}
  • 1
    You can shorten with a function like this: codegolf.stackexchange.com/a/140570/46313 – geokavel Aug 27 '17 at 20:18
  • Or, if you want to stick with Java 7, you can submit a method definition, e.g. int f(String s){ ... }. Also, you can save bytes by using Long.toHexString and Long.parseLong. – Jakob Aug 27 '17 at 20:32
  • Also, remove the space after String[]. – Zacharý Aug 27 '17 at 20:32
  • @Downvoter: Why? – Shaggy Aug 27 '17 at 21:30
  • As @geokavel mentioned, you can use a Java 8 lambda to shorten your code, since you didn't specify in your challenge you should have a full program, and the default here on PPCG is "program or function/lambda": s->Long.toHexString(Long.parseLong(s,2)). But, if you want to stick with a full program, you can also shorten it with Java 8 by replacing class A{public static void main(String[]a){ with interface A{static void main(String[]a){. – Kevin Cruijssen Sep 1 '17 at 13:26

PHP, 25+1 bytes

<?=dechex(bindec($argn));

Run as pipe with -F.

or 27+1 bytes: (-R)

printf("%x",bindec($argn));

or 28+1 bytes: (-F)

<?=base_convert($argn,2,16);

or 30+1 bytes: (-R)

eval("printf('%x',0b$argn);");

C, 168 bytes

i,l,k,n;f(char*s){char*o=malloc(l=strlen(s));for(i=n=0;i<l;n+=k<<i++)if((k=s[l-i-1]-48)&&k-1)return 0;for(i=o[--l]=0;n;n/=16)k=n%16,o[l-++i]=k>9?k+55:k+48;puts(o+l-i);}

Try it online!

Unrolled:

i,l,k,n;
f(char *s)
{
    // Allocate a string for the hexadecimal digits.
    // The number of digits in the hex number is
    // sure to be less or equal to that of binary.
    char *o = malloc(l=strlen(s));

    // Convert binary to decimal.
    // The function returns zero without printing
    // anything if there are extraneous characters.
    for (i=n=0; i<l; n+=k<<i++)
        if ((k=s[l-i-1]-48) && k-1) return 0;

    // Convert decimal to hexadecimal.
    for (i=o[--l]=0; n; n/=16)
        k = n%16, o[l-++i] = k>9 ? k+55 : k+48;

    // Print the number in hexadecimal.
    puts(o+l-i);
}

Retina, 72 70 bytes

A`[^01]
T`d`l`.(?!(....)*$)
T`d`23`b\d
T`d`4-7`b.\d
T`d`89L`b..\d
a|b

Try it online! Output is blank on error. Edit: Saved 2 bytes thanks to @PunPun1000. Explanation:

A`[^01]

Delete non-binary input.

T`d`l`.(?!(....)*$)

Convert all digits not in the correct position to as and bs instead.

T`d`23`b\d

Add 2 to digits that follow a b.

T`d`4-7`b.\d

Add 4 to digits two after a b.

T`d`89L`b..\d

Add 8 to digits three after a b.

a|b

The as and bs have done their job and can be deleted.

  • 89A-F can be replaced with 89L assuming I'm reading your explanation correctly – PunPun1000 Aug 28 '17 at 13:55
  • @PunPun1000 Thanks for reminding me; I knew there was something I'd overlooked. – Neil Aug 28 '17 at 14:48

CJam, 17 bytes

{2bGb{_9>'70?+}%}

Function that takes an array of bits as input.

Test Version

{
2b     e# Convert from base-2 to base-10.
Gb     e# Convert from base-10 to base-16.
{      e# For each digit in the hex version...
_      e# Duplicate it.
9>     e# Check if it's greater than 9.
'70?   e# If it is, add a '7' (char) to the stack. If not, add a 0 (int).
 +     e# Add the new item to the digit. Int + char => Increment char's ASCII value by int. (e.g '7' + 10 = 'A')
}%
}

If necessary, here's a version that checks for invalid input (29 bytes):

{_2,|$2,=1W?*2bGb{_9>'70?+}%}

Test Version

It outputs 0 for an empty array and throws an exception for all other invalid input.

How validation works....

{
_2,|$  e# Get Logical OR of input array and [0,1], sorted.
2,=    e# Does that equal [0,1]?
1W?    e# If the arrays are equal add 1 to the stack, if not add -1.
*      e# Repeat the input as many times as the number just added to the stack. 
       e# If the number is 1, the input is unchanged.
       e# If it's -1 you get an error for an invalid number of repetitions.
...
  • Does not exit, error or yield 0 for all invalid inputs. – Jonathan Allan Aug 27 '17 at 23:16
  • @Jon I did it this way because of the comments on caird's Osabie answer. I guess it's not clear what "error" as a verb means. – geokavel Aug 27 '17 at 23:40
  • There would be no point in specifying that the program should "do something unexpected given invalid input" as there is no valid output for invalid input, so I think "should error" is pretty clear (although as I commented under the OP I think input validation should really be avoided). – Jonathan Allan Aug 27 '17 at 23:43

R, 34 bytes

function(x)as.hexmode(strtoi(x,2))

Returns NA for invalid input.

Try it online!

6502 machine code (C64), 100 bytes

00 C0 20 FD AE 20 9E AD 20 A3 B6 8D 1C C0 A0 00 84 FB 84 FC 29 03 AA D0 16 A2
04 A4 FB C0 FF D0 0E A4 FC A9 00 99 62 C0 A0 C0 A9 62 4C 1E AB A9 00 85 FE CA
30 1B 06 FE A4 FB E6 FB B1 22 C9 30 F0 F1 C9 31 F0 03 4C 99 AD A5 FE 09 01 85
FE D0 E2 A9 30 05 FE C9 3A 30 02 69 06 A4 FC 99 62 C0 E6 FC D0 B5

Online demo

Usage: sys49152,"[input]", where [input] is your binary string, e.g. sys49152,"10000000010100100000".

Important: When the program was loaded from disk (like in the online demo!), issue a new command first! This is because loading the program fiddles with some BASIC pointers and the machine thinks there's no RAM left for a string...


Explanation (commented disassembly listing):

00 C0       .WORD $C000         ; load address
20 FD AE    JSR $AEFD           ; check for comma
20 9E AD    JSR $AD9E           ; evaluate expression
20 A3 B6    JSR $B6A3           ; get string from expression
8D 1C C0    STA $C01C           ; store input string length for CPY instruction
A0 00       LDY #$00            ; initialize counters to 0:
84 FB       STY $FB             ;    read counter
84 FC       STY $FC             ;    write counter
29 03       AND #$03            ; number of bits in first incomplete nibble
AA          TAX                 ;  -> to X register
D0 16       BNE .nibble         ; branch to nibble decoding if not 0
 .mainloop:
A2 04       LDX #$04            ; from here on 4 bits per nibble
A4 FB       LDY $FB             ; load read counter to Y
C0 04       CPY #$FF            ; compare with input length (argument modified)
D0 0E       BNE .nibble         ; not yet done -> branch to nibble decoding
A4 FC       LDY $FC             ; load store counter
A9 00       LDA #$00            ; write NUL terminator 
99 62 C0    STA .outbuf,Y       ; to output string
A0 C0       LDY #$C0            ; load address of
A9 62       LDA #$62            ; output string
4C 1E AB    JMP $AB1E           ; and jump to string output routine
 .nibble:
A9 00       LDA #$00            ; initialize value of nibble to zero
85 FE       STA $FE             ; store to temporary variable
 .nibbleloop:
CA          DEX                 ; decrement number of bits
30 1B       BMI .nibbleout      ; no bits left -> prepare for output
06 FE       ASL $FE             ; shift temporary variable left
A4 FB       LDY $FB             ; load read counter to Y
E6 FB       INC $FB             ; increment read counter
B1 22       LDA ($22),Y         ; load next input character
C9 30       CMP #$30            ; compare with '0'
F0 F1       BEQ .nibbleloop     ; if equal, handle next bit
C9 31       CMP #$31            ; compare with '1'
F0 03       BEQ .nibbleadd      ; if equal, add that bit
4C 99 AD    JMP $AD99           ; neither '0' or '1' -> type mismatch error
 .nibbleadd:
A5 FE       LDA $FE             ; load temporary variable
09 01       ORA #$01            ; set lowest bit
85 FE       STA $FE             ; store temporary variable
D0 E2       BNE .nibbleloop     ; handle next bit
 .nibbleout:
A9 30       LDA #$30            ; load character '0'
05 FE       ORA $FE             ; combine with value from temporary variable
C9 3A       CMP #$3A            ; result smaller than 0x39 ('9') ?
30 02       BMI .nibblestore    ; then store that
69 06       ADC #$06            ; otherwise add offset to get in range 'a'-'f'
 .nibblestore:
A4 FC       LDY $FC             ; load write counter
99 62 C0    STA .outbuf,Y       ; write to output string
E6 FC       INC $FC             ; increment write counter
D0 B5       BNE .mainloop       ; back to main loop
 .outbuf:                       ; "BSS", output string is stored from here

Remarks:

  • Input validation is fully implemented (and takes quite a few bytes, otherwise it would be possible to directly output each decoded nibble without temporary storage)

  • I took the liberty to interpret "any length" as "any length my C64 system can read from a command line as a string", which is quite limited ... 69, or if you abbreviate sys with sY 70 "bits", because the whole command line is limited to 80 characters ... hope this is acceptable :)

Screenshot

05AB1E, 7 6 bytes

CbQ*Ch

Try it online!
Error case

It's my first try ever to a Code Golf, advices welcomed!
Handles error cases \o/

The idea is to make the conversion from base 2 to base 10, and back to base 2. Compare the result with the initial input, if it's not the same, then the conversion have failed.

1012101 => 0
a => empty
-1010101 => 0
abcdef => empty
2 => 0

Explanation

CbQ*Ch
C  # convert input from base 2 to base 10
 b # ...and back to 2
  Q # 1 if the full conversion back and return equals the input, else 0
   * # multiply to get 0 if error case
    C # convert corrected input from base 2 to base 10
     h # convert it to base 16 
  • 1
    You could use b instead of 2B – Emigna Sep 5 '17 at 13:52

Ruby, 27 25 bytes

->b{'%x'%Integer('0b'+b)}

Try it online!

-2 bytes thanks to histocrat.

Inputs and outputs strings.

String#to_i vows to never throw an exception, returning 0 for many invalid inputs. That would be fine, except for this property:

Extraneous characters past the end of a valid number are ignored.

Meaning that 1012101 is read up to the 2 and interpreted as 101 (or 5), which is no good. We can use the stricter Integer() instead, which throws an exception for any number that is not binary. It lets through negative numbers, so we need to invalidate those by prepending 0b to the input. 0 as input returns 0, which is within the specification.

  • I don't think you need the ,2 unless I'm missing some corner case, since you're already specifying base 2 with the '0b'. – histocrat Nov 20 '17 at 22:39
  • @histocrat This was long enough ago that I can't really remember but I suspect you're right. Thanks! – Snack Nov 21 '17 at 22:31

Tcl, 66 bytes

proc H b {expr {[regexp ^\[01\]+$ $b]?[format %x [scan $b %b]]:0}}

Try it online!

  • There was a bug in fifth test case. Fixed now. – sergiol Dec 23 '17 at 11:39

Rust, 58 57 bytes

Saved one byte using 8 bit int

|n:&str|format!("{:x}",u8::from_str_radix(n,2).unwrap());

Ungolfed

fn main() {
    let bin = "101";
    println!("{:x}", u8::from_str_radix(bin, 2).unwrap()); // 5
}

Try it online!

Python 3, 52 29 26 bytes

print(hex(int(input(),2)))
  • It's not very golfy – Zacharý Aug 27 '17 at 20:33
  • Unfortunately, since the OP changed the rules it now only differs by being a more verbose function definition. – cole Aug 27 '17 at 21:17
  • ...plus (like the other one) does not exit, error or yield 0 for all invalid inputs. (Also you have not updated the TIO link from the 52 byter) – Jonathan Allan Aug 27 '17 at 23:09
  • You might be able to change it to Python2 (and remove the parens after print), since it would error on invalid inputs due to various different reasons. – Zacharý Aug 27 '17 at 23:22
  • @Zacharý Sadly Python 2 doesn't seem to have a hex() builtin – benzene Aug 27 '17 at 23:27

Stacked, 24 bytes

[:\'1|0'-#'0=\unbin*hex]

Try it online!

Dyvil, 32 Bytes

s=>Int.parseInt(s,2).toHexString

Pretty much self-explanatory. Throws a NumberFormatException for invalid inputs. Output without 0x.

Javascript (ES6) 50 45 39 bytes

h=
s=>isNaN(n=+('0b'+s))?0:n.toString(16)   
<input id="i" type="text" onchange="o.innerHTML=h(i.value)"><pre id="o"></pre">

with thanks to Shaggy 6 bytes less. Or for a 26 byte version that returns 'NaN' instead of '0' on error:

s=>+('0b'+s).toString(16)

'0b' was introduced as a binary number prefix in ES6.

  • You should be able to save some bytes by moving the assignment of n within isNaN and then removing the parentheses from the function parameter. Also, does the 0 need to be a string? – Shaggy Aug 28 '17 at 7:29
  • @Shaggy - new ways to be sneaky, thanks. And also agree that 0 converts to '0' automatically when inspecting/printing the result. – traktor53 Aug 28 '17 at 9:36

Python 2, 27 bytes

lambda s:hex(int('0b'+s,2))

Try it online!

We invalidate inputs like 0b1010 or -1010 by prefixing 0b ourselves — because 0b0b1010 and 0b-1010 are invalid base 2 literals in Python.

  • eval('0b'+s) for a byte – Uriel Aug 28 '17 at 15:48
  • No, it’s too strong! Inputs like "0+4*5" will yield 20. – Lynn Aug 28 '17 at 17:28

Perl 6, 19 bytes ( = 18 + 1 for "-p" )

perl6 -pe '$_=:2($_).base: 16'

Nothing creative. The :2(string) construct takes the string and interprets it as a number in base 2. (This works for arbitrary bases up to base 36.) The base method takes a number and gives a string representation in the given base.

Due to -p, it loads one line from stdin at a time, expecting each to contain one number. If you feed it something that's not valid binary number, you get an error and the program ends.

Javascript, 28 bytes

x=>eval("0b"+x).toString(16)

evals x with a 0b in front of it, turning it into a binary literal. Binary literals error out on non binary values of x. .toString(16) turns x into a hexdecimal.

Perl 5, 30 + 1 (-n) = 31 bytes

printf"%x",!y/01//c&&oct"0b$_"

Try it online!

REXX, 15 bytes

say b2x(arg(1))

Common Lisp, 48 bytes

(format t"~X"(parse-integer(read-line):radix 2))

Try it online!

Julia, 24 bytes

f(x)=hex(parse(Int,x,2))

Try it online!

Bash, 19 bytes

printf %x $((2#$1))

Try it online!

><>, 84 82 Bytes

Improved somewhat. Probably still improvable.

l&1>:}*{$}2\~-?\02.
~~&\?&:-1&*/1l+<
>:f1+%:}\
\?:,+1f-/.47r~
)a:;!?ln/?
.47o+*b5/

Old version:

1l&>:}*{$}2\
~~&\?&:-1&*/l +<
>:f1+%:}-f1\1-?/
\?      :,+/r~
n/?)a:;!?l <
5/.4co+*b

I'll work on improving it later, see if I can get rid of that big chunk of whitespace.

How it works:

(This is for the old version, new version works the same but with loops in different positions)

Implicit input, assumed to be a series of bits such as '1,1,1,0,0', with the ones place on the right, as normal.

l&1

Store the length in the registry; push 1 to the stack. The 1 will record which place we are on in the binary number.

   >:}*{$}2\
   \?&:-1&*/

Replace each bit with the value it represents. For example, 1,1,1,0 goes to 8,4,2,0.

~~&

Delete the counter and position-measurer.

           /l +<
           \1-?/

Sum the stack. Results in the number that was represented in binary.

>:f1+%:}-f1\
\?      :,+/

Convert this to hexadecimal, which unfortunately reverses it and leaves a trailing 0. For example, 28 becomes 12, 1, 0.

           /r~

Remove the trailing zero and un-reverse it.

n/?)a:;!?l <
5/.4co+*b

This is all for printing. If the value is <10, just print it normally. Otherwise, add 55 and print the ascii character of this number.

Lua, 43 40 bytes

print(("").format("%x",tonumber(...,2)))

I think it explains itself. Parses from base 2 to decimal then formats it to hex. If it is not binary input it will simply error (tested with Lua 5.2,5.3).

><>, 50 bytes

{:?v~
!v0>}l4%?
 r
4<]nv?)9:+++*2}*4}*8[
+"W"<.33o

Try It Online

Complies with the question by erroring on invalid input, but as it always ends with an error anyway, this is a bit tongue in cheek.

How It Works

{:?v~ Pops leading 0s
...

...
!v0>}l4%? Adds leading 0s until the length of the binary is divisible by 4
 r        And reverses the input
...

...                   Repeatedly take the last 4 digits of the binary
4<]nv?)9:+++*2}*4}*8[ Calculate the value of those digits and print the hexadecimal value
+"W"<.33o             If the value is above 9, print the appropriate letter

Kotlin 1.1, 92 bytes

Submission

fun r(i:String):String{return if(i.matches(Regex("[01]+")))i.toLong(2).toString(16)else "0"}

Beautified

fun r(i: String): String {
    return if (i.matches(Regex("[01]+"))) {    // If it is valid
        i.toLong(2)                            // Convert to Long
         .toString(16)                         // Return as hex
    } else {                                   // Otherwise
        "0"                                    // Return 0
    }
}

Explanation

  • The number is checked to be valid by the regex
  • Kotlin to and from string methods are used to convert the string

Unfortunately this does not run on TryItOnline, as it uses newer Kotlin features

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.