Number Base Converter Internals: Binary, Hex, Octal, and the 2 to the 53 Wall

Converting between binary, hex, octal, and decimal is textbook material. The interesting parts of a real converter are the edges, which inputs get rejected, why parseInt alone is dangerous, and where floating point silently corrupts results. This site ships a number base converter, and its source code in src/components/NumberBase.tsx makes a good specimen. Here is what it does, worked through examples you can verify by hand.

Four bases, one parse, one check

The tool supports exactly four source bases, 2, 8, 10, and 16, and shows all four outputs at once. Conversion runs in two steps. First parseInt parses the input with the selected radix. Second, a character loop validates every input character against the string 0123456789ABCDEF cut to the base length, so base 2 accepts only 01, base 8 accepts 0 through 7, and base 16 accepts digits plus A through F.

Input is uppercased before the check, so lowercase hex like 2f is accepted. Output is uppercased too, so decimal 255 prints as FF in the hex row, alongside 11111111 in binary and 377 in octal.

Why the second step exists

parseInt stops at the first character it cannot use and returns what it parsed so far. Type 12AB with base 10 selected and plain parseInt would silently return 12. The character loop rejects the whole input instead and shows an invalid number message.

That second check is the difference between a converter and a bug generator. Several other rejections fall out of the same rule.

  • The 0x prefix fails, because X is not a valid hex digit in the checker, even though parseInt alone would accept 0x1F as 31.
  • Negative numbers fail, because the minus sign is not in the digit set.
  • Decimal points fail, so the tool is integers only.
  • Spaces fail, including trailing ones you cannot see.

None of these produce wrong answers. They produce no answer, which is the correct behavior for an integer converter.

Grouping shortcuts that beat conversion

You rarely need division to move between binary, octal, and hex, because the bases divide evenly.

Each hex digit is exactly four binary digits, and each octal digit is exactly three. Take the binary value 11010110. Split it from the right into fours, 1101 and 0110, map 1101 to D and 0110 to 6, and you get D6 hex. Split the same bits into threes, 11, 010, and 110, map to 3, 2, and 6, and you get 326 octal. Both equal 214 in decimal, which the tool confirms in one keystroke.

Reverse the process to go back. Hex 2F expands to 0010 and 1111, giving 101111 binary, which is 47 decimal and 57 octal.

The 2 to the 53 wall

The converter stores results as a JavaScript number, not a BigInt. A double carries 53 bits of integer precision, which caps exact integers at 2 to the 53, or 9007199254740992.

Enter 9007199254740993 in base 10 and the tool reports outputs for 9007199254740992, one value lower. The low bit is not representable, the parse rounds, and the binary row ends in 0 instead of 1. There is no warning, because neither parseInt nor toString signals precision loss.

The rule is simple. Trust the outputs for values up to 2 to the 53. Above that, convert in pieces or use a BigInt based tool. For reference, 2048 is only 2 to the 11, and even the extreme tile in the game engine, 131072, is 2 to the 17, both far inside the safe range.

Where number bases appear in this site's own code

Two examples from this repository show the bases at work.

The 2048 game engine stores every tile color as a 24 bit hex literal in its color map. The tile with value 8 uses f2b179, where f2 sets red, b1 sets green, and 79 sets blue. Web colors are just hex numbers, and the converter turns f2 into 242 decimal or 11110010 binary when you need the channel value.

The same engine computes its merge sound pitch with Math.log2 applied to the merged tile value, minus 1. That line works because every legal tile value is a power of two, from 2 up to 2048, so the logarithm is always an exact integer. It is a small demonstration of why binary thinking pays off outside a converter page.

Stated limits

The tool converts integers between bases 2, 8, 10, and 16 only. There is no arbitrary radix input, so base 5, base 32, or base 64 encoding is out of scope. There are no negative numbers, no fractions, and no BigInt path past 2 to the 53. Output is uppercase only, which matters if you paste results into systems that treat ff and FF differently, such as some DNS tooling and older config parsers.

Conversion checklist

  • [ ] Strip prefixes like 0x before pasting, the validator rejects them.
  • [ ] Integers only, cut any decimal part first.
  • [ ] Binary to hex in groups of four, binary to octal in groups of three.
  • [ ] Values above 2 to the 53 verified with a BigInt tool.
  • [ ] Output is uppercase, downcase it yourself where the target system is case sensitive.

Try these examples on the [number base converter](/number-base-converter), especially the 9007199254740993 case, because seeing the silent low bit change is worth more than reading about it. If you hit an input that the tool mishandles in a way this article does not list, send it in, along with the base you selected, and it will extend the failure catalog.