Number base converter

Converts a number between binary, octal, decimal, hexadecimal and any base from 2 to 36, with fixed-width two’s complement and a clickable bit grid.

Width
Binary
Octal
Decimal
Hexadecimal
Base
Bits — click to flip

8 bits wide, 8 set

What this tool does

The same number can be written in many bases, and programmers move between four of them constantly: binary because that is what the hardware holds, hexadecimal because it is a readable shorthand for binary, decimal because that is how people think, and octal because file permissions and a few older systems still use it. Type a value into any of the fields here and the rest follow, along with one more field you can set to any base from 2 to 36.

What separates this from a school calculator is the width selector and the bit grid. Pick 8, 16, 32 or 64 bits and negative numbers get their real machine representation instead of a minus sign, and every bit becomes something you can click.

What a base actually is

A base is how many digits you have before you run out and have to carry. Decimal has ten, so after 9 comes 10. Binary has two, so after 1 comes 10. The position of each digit is a power of the base, and that is the whole of it:

1011           # the number, in base 2
1 x 8 = 8      # bit 3
0 x 4 = 0      # bit 2
1 x 2 = 2      # bit 1
1 x 1 = 1      # bit 0
8+0+2+1 = 11   # the total, in decimal

Bases above ten need more than ten digit symbols, so they borrow letters: hexadecimal runs 0-9 then a-f, where a is 10 and f is 15. That continues all the way to base 36, which uses every digit and every letter — the largest base you can write with the plain alphabet, and the reason this tool stops there.

Why hexadecimal, and not something else

Hex is popular for one specific reason: 16 is 2 to the power of 4, so exactly one hex digit covers exactly four bits. That makes the conversion between hex and binary a lookup with no arithmetic — each hex digit expands to its own four bits, independently of the digits around it.

d    e    a    d
1101 1110 1010 1101   # each hex digit is its own nibble

Octal works the same way with three bits per digit, since 8 is 2 to the power of 3 — which is why Unix permissions are octal: three permission bits per group of users fits one digit exactly. Decimal has no such relationship with binary, which is why converting between them requires real division rather than a lookup.

This is also why the binary field here is grouped into fours and the hex field into pairs: the groups line up with the boundaries that matter, so you can read a nibble or a byte off the screen without counting.

Negative numbers and two’s complement

A negative number has no binary form on its own. There is no minus sign in a register — only bits — so the sign has to be encoded in the bits themselves, and that requires deciding how many bits there are. This is why the width selector exists, and why the answer changes when you change it.

The scheme every modern machine uses is two’s complement: to represent a negative number, take its positive form, invert every bit, and add one. The result is that the top bit ends up meaning "negative", and ordinary addition keeps working without any special case for signs.

0000 0101   # 5
1111 1010   # every bit inverted
1111 1011   # plus one: -5 as a byte, or fb in hex

Widen the register and the same number gets a different pattern: -5 is fb in 8 bits, fffb in 16 and fffffffb in 32. The value has not changed; the number of bits carrying it has. Switching width in this tool shows exactly that.

Why 0xFF is both 255 and −1

The bits ff do not say whether they are signed. A byte holding 1111 1111 reads as 255 if the code that loads it declared an unsigned type, and as −1 if it declared a signed one. Nothing in the byte itself distinguishes the two — the type is a claim the program makes about bits that carry no such information.

That is the source of a whole family of real bugs: a checksum that comes out negative, a byte read from a file that compares as less than zero, a C char that behaves differently on ARM than on x86 because its signedness is implementation-defined. Whenever the signed and unsigned readings differ, this tool shows both, because the mismatch is usually the thing you were looking for.

The bit grid

Every bit of the current value is shown with its position number, and clicking one flips it. The bases update immediately, which makes a few questions much easier to answer than by hand:

  • Which bit is set in this flag value — click through them and read the positions.
  • What is the mask for bits 4 and 7 — set those two and read the hex.
  • What does setting the top bit do to a signed value — it turns it negative, visibly.
  • Is this value a power of two — a power of two has exactly one bit set.

Bit 0 is the least significant bit and sits on the right, which is the universal convention and the reason the grid stays left-to-right even on a right-to-left page. Rows are eight bits wide so byte boundaries are visible at a glance.

Large numbers stay exact

JavaScript numbers are doubles, which hold integers exactly only up to 2^53 — about 9 quadrillion. A 64-bit value can exceed that, and a converter built on ordinary numbers will quietly round it, giving a hex string that looks plausible and is wrong in its last digits.

Everything here uses arbitrary-precision integers instead, so a full 64-bit value converts exactly. The arbitrary-precision width mode goes further and removes the limit entirely — useful for cryptographic values and large identifiers — but note that without a fixed width there is no two’s complement, so a negative number in that mode simply carries a minus sign in every base.

Binary to decimal, and decimal to binary

Binary and decimal are the one pair here that shares nothing: two is not a power of ten and ten is not a power of two, so neither direction is a lookup and both need real arithmetic. They are also not the same arithmetic, which is the part rarely said out loud — the quick hand method going one way is not the reverse of the quick hand method coming back.

  • Binary to decimal, by doubling: start at the leftmost bit with nothing, then for each bit double what you have and add that bit. For 1011 that runs 1, 2, 5, 11 — one pass, no place values to remember, and it is exactly what this tool does when it reads what you type.
  • Binary to decimal, by position: add up the place value of every bit that is set, which is the worked example further up. Quicker when only two or three bits are set, slower when most of them are.
  • Decimal to binary, by dividing: divide by two and write down the remainder, again and again, until nothing is left — then read the remainders bottom to top. The answer arrives least significant bit first, which is why it looks backwards the whole time you are writing it.
  • Decimal to binary, by subtracting: take away the largest power of two that fits, and repeat. 200 loses 128, leaving 72; 72 loses 64, leaving 8; 8 loses 8, leaving nothing — so the bits at positions 7, 6 and 3 are set and the byte is 1100 1000. Faster than dividing whenever few bits are set.

One thing no hand method here covers: a negative decimal number has no binary form at all until a width is chosen. Ask for minus five in binary and the honest answer is a question — how many bits? — which is what the width selector settles and what the section on two’s complement above is about. In arbitrary-precision mode there is no width, so the minus sign simply comes along into every base.

Decimal to hex, and hex to decimal

Almost nobody who does this often divides by sixteen. Hexadecimal’s relationship with binary is the shortcut: convert the decimal number to binary once, cut the bits into groups of four from the right, and read each group as a single hex digit. Coming back is the same route reversed — expand each hex digit into its four bits, then add the place values of the bits that are set. For anything up to a byte there is a shorter way still: the first hex digit is worth sixteen of the second, so multiply and add.

  • 255 is ff — a byte with every bit set. It is the one worth knowing by heart, because it is where a byte stops.
  • 256 is 100. One past a full byte the digits roll over, exactly as 99 rolls over to 100 in decimal, and the hex number gains a digit the byte cannot hold.
  • 65535 is ffff and 65536 is 10000: the same two landmarks one byte further up, which is where a sixteen-bit counter stops.
  • 4096 is 1000, which is why page sizes, alignments and memory offsets look round in hex and ragged in decimal. Hex counts in fours of bits, and so does the hardware.

Case is not significant: FF and ff are the same value, this tool accepts either on the way in and prints lowercase on the way out. What it will not do is guess. A 0x belongs to the hexadecimal field and is refused in the decimal one rather than quietly dropped, because a value that parses in the wrong base is the one mistake a converter must never make look plausible.

Octal to decimal, and the leading zero that changes the answer

Octal survives in one place above all others: file permissions, where three bits of permission per class of user fit one octal digit exactly. Converting it to decimal is plain positional arithmetic with powers of eight — 755 in octal is seven sixty-fours plus five eights plus five, which is 493 — and the other direction is divide-by-eight with the remainders read bottom to top, the same shape as decimal to binary and for the same reason: eight has no relationship with ten either.

  • 755 is 493 in decimal, 644 is 420, and 777 is 511. Not one of those decimal numbers is any use to anybody, which is the point — permissions are written in octal because the digits line up with the permission bits, not because the value counts anything.
  • A leading zero is a base marker in C and in Python 2, where 0755 is octal and therefore the number 493. Python 3 refuses that spelling outright and wants 0o755 instead, which removed a whole class of quiet bug.
  • YAML 1.1 reads an unquoted 0755 as 493 as well, which is why a permission mode in a configuration file has to be quoted or it stops being the mode you wrote.
  • JSON never allowed it. Its grammar forbids a leading zero on a number, so 0755 is not a number there at all but a parse error — the loudest of the three behaviours, and the only one that cannot be misread.

This tool treats a bare leading zero as a marker of nothing. The field you type into decides the base, so 0755 in the decimal field is 755 and in the octal field is 493, and the 0o prefix is accepted in the octal field and refused everywhere else. Guessing a base from a prefix would mean handing back a different number from the one that was typed.

Octal to hex: the pair with no shortcut

Both are powers of two, so both are pure regroupings of the same bits — and yet this is the one pair among the four bases with no digit-for-digit rule at all. One octal digit is three bits, one hex digit is four, and neither of those divides into the other, so the boundaries never line up. There is no way round writing the bits out and regrouping them.

  • Write each octal digit as its own three bits, in order: 755 becomes 111 101 101.
  • Regroup those bits into fours from the right-hand end, padding the left with zeros where the count does not divide evenly: 0001 1110 1101.
  • Read each group of four as one hex digit: 1ed. Padding the wrong end is the classic error here, and it does not look wrong — it silently multiplies the answer.

That two hex digits are exactly one byte, and two octal digits are not, is the whole reason hex displaced octal for reading memory: eight bits is two and two-thirds octal digits, so a byte boundary falls in the middle of a digit. Octal suited machines whose word sizes were multiples of three bits; hex suits the eight-bit byte. And on this page the bit grid is faster than either hand method for this pair — set the bits once and both fields are already showing the answer.

Frequently asked questions

Why does −5 show as fb instead of −101 in binary?
Because a register has no minus sign. With a width selected, negative numbers are shown in two’s complement, which is what the machine actually stores: −5 in a byte is 1111 1011, or fb. If you want the mathematical form with a sign, switch the width to arbitrary precision.
Is 0xFF 255 or −1?
Both — the bits are identical and only the declared type decides. A signed 8-bit value reads ff as −1; an unsigned one reads it as 255. Whenever the two readings differ, this tool shows them side by side.
Why is hexadecimal used so much instead of decimal?
Because one hex digit is exactly four bits, so hex and binary convert by lookup with no arithmetic and the digits line up with byte boundaries. Decimal has no such relationship with binary, so a decimal value tells you nothing about which bits are set.
What is the highest base here, and why 36?
36, because that is 10 digits plus 26 letters — every symbol the plain Latin alphabet offers. Going higher would need a convention about which extra characters to use, and there is no single agreed one.
Can I paste a value with 0x or spaces in it?
Yes. The 0x, 0b and 0o prefixes are accepted in their matching base, and spaces and underscores are ignored, so you can paste straight from code or a datasheet without cleaning it up first.
Will a 64-bit value convert exactly?
Yes. All the arithmetic uses arbitrary-precision integers, so values beyond 2^53 — where an ordinary JavaScript number starts rounding — stay exact.
Is anything I type sent to a server?
No. It is arithmetic in your browser; nothing is uploaded or logged, and it works with no network connection.
How do I convert binary to decimal by hand?
Double and add, from the left: start with nothing, and for each bit double what you have so far and add the bit. 1011 goes 1, then 2, then 5, then 11. It is one pass with no place values to remember, and the same method works in any base — multiply by the base instead of doubling.
What is 255 in hex, and why does that number keep turning up?
ff. It is a byte with all eight bits set, so it is the largest value one byte holds and the point where the count rolls over into a second byte — which is why it turns up in color channels, masks and size limits everywhere. One more than it is 256, written 100 in hex.
Is 0755 the same number as 755?
Here, yes in the decimal field and no in the octal one: the field decides the base, and a leading zero is simply a zero digit. Elsewhere it depends on the language — C and Python 2 read 0755 as octal, which is 493; Python 3 rejects that spelling and wants 0o755; YAML 1.1 reads it as 493; JSON treats it as a syntax error.
How do I convert octal to hex?
Through binary, because there is no shorter route: three bits per octal digit, four per hex digit, and the two never line up. Expand each octal digit into its three bits, regroup the whole run into fours starting from the right, and read each four as a hex digit — 755 becomes 111 101 101, then 0001 1110 1101, then 1ed.

Related tools

  • Byte size converter

    The same number read as an amount of storage rather than as a pattern of bits: that page turns a byte count into KB, MB and GB beside KiB, MiB and GiB, and says where the two systems disagree.

  • Percentage calculator

    A base is how a number is written down; a percentage is how big it is beside another one. That page works out shares, changes and reversals, and prints the arithmetic with your own figures in it.