Base Converter - Every Base from Two to Thirty-Six, One Digit at a Time
Convert any integer or decimal fraction between base 2 and base 36 and read the work: the digit-by-digit ledger, which bases the number ends in and which repeat forever, the bytes at 8, 16, 32 and 64 bits in both endians, and a differential run against your own browser's Number, parseInt, BigInt and DataView at the bottom - with the size of every difference printed as a number. Nothing you type leaves this device.
Read one digit at a time, the way the arithmetic did it
| Which digit | The character | Its value | The total so far | The rule |
|---|
The same number in every base, and what your own browser prints beside it
| The base | What the long division wrote | How it ends | What your Number wrote | Why, where they differ |
|---|
The whole part laid out as bytes, against your browser's DataView
| The row | These bytes | DataView's | It reads | What to notice |
|---|
Declined to answer
| The thing it stopped on | What it says instead | Times |
|---|
Against your own browser
| The rule | What the converter made | What your browser made |
|---|
Bases, long division, the differential
A base is a way of writing, not a value
A base is a way of writing a value, not a value itself. The digits 1011 mean eleven when the base is
two and one thousand and eleven when the base is ten; the pile of objects on the table does not change,
only the way it is written down. So the work goes in two steps, and keeping them apart is the whole
design:
- Read your digits into one exact number. A numeral is a run of digits before a point and a run after it. The first becomes a whole number by the rule in the first table - total so far times the base, plus this digit. The second becomes a count of parts, each one divided by the base as many times over as there are digits. Add them, cancel the common factor, and you have one whole number over one whole number. That pair is the number. It is held in full, with no fixed-width box around it, so the twenty-first digit of a long numeral is as true as the first.
- Write that pair out again by long division. For base five, divide and keep the remainder, multiply the remainder by five, divide again. When the remainder reaches nothing the expansion ends. When a remainder turns up a second time, the digits between the two visits repeat forever, and the long division puts that block in brackets. Every base in the table comes from the same pair, so the columns really are the same number written different ways - which is the claim the table can be checked against.
That is all the arithmetic. Nothing is scaled, rounded or fitted into sixty-four bits before it is printed.
The four tables
Digit by digit - your numeral one character at a time: the character, the value the converter gives it, and the total so far. It is the longest division in school done in public, and it is where a digit from another script, a comma, an underscore or a stray letter gets named instead of quietly ignored.
Every base - the same number written in base two through thirty-six, with four things said about
each: the digits, whether they end, whether they repeat, and what your own browser’s Number prints for
the same value. The group picker shows the four bases people meet most, all thirty-five, only the ones
this number ends in, or only the ones it repeats in. Thirty-five rows of long digit strings is a lot to
read at once, which is why the default is the four.
Bytes - the whole part of your number laid out at 8, 16, 32 and 64 bits, big-endian and little, read
as unsigned and (if you ask) as signed. Each row prints the converter’s own bytes and your browser’s
DataView beside them. A number that does not fit is not refused here: the converter prints its low bits,
because that is exactly what a machine keeps when you put the number in a box that small, and it says so
in the last column.
Against your own browser - twenty-odd rows where the converter’s answer and the engine’s answer are put side by side. It is a differential, not a test of your machine: every row is the same question asked of two implementations, and the verdict column says which answers matched.
Which bases a number ends in, and which it cannot
A fraction ends in a base if its reduced denominator can be cancelled by powers of that base, and repeats forever if it cannot. One fifth - reduced, denominator five - ends in base five, ten, fifteen, twenty, twenty-five, thirty and thirty-five, and nowhere else from two to thirty-six. One third ends in base three and nowhere else. One tenth ends in base ten, twenty and thirty. Ten sixteenths is not interesting: reduced it is five eighths, and eight is a power of two, so it ends in base two, because “ends” is a fact about the number, not about how you happened to write it.
The summary line at the top says this outright for whatever you typed, because it is the one question about a fraction that has a clean answer. And it is the reason a decimal fraction and a binary machine disagree so often: a double is a whole number over a power of two, so it can hold tenths, twelfths and four-hundred-and-ninths only as an approximation. That is not a bug in the browser and not a limitation of the converter. It is the same fact as “one third has no last digit in base ten”, moved to a number system whose base is two.
Why the last column is a number and not a warning
Ask Number for 18446744073709551615.2 and it answers 18446744073709552000. Most pages would print
a caution here. The arithmetic reads the sixty-four bits your browser kept for that answer, decodes them as
what a double really is - a whole number times a power of two - and subtracts. The gap turns out to be
0.8, and it is printed beside the row. Every difference in the bases table and the differential gets
the same treatment: the exact ratio behind the browser’s digits is worked out, and the distance between
the two numbers is given as a number in base ten.
Three thresholds are worth knowing, and each has a row that shows it rather than asserts it:
- Nine quadrillion, one hundred and seven trillion… -
9007199254740991, the largest integer a double holds with no neighbour competing for the same slot. Past it, whole numbers start being rounded to the nearest even one that fits, and the row prints by how much. - The exponent.
Number.prototype.toStringwith a base argument never usese, but plaintoStringswitches to exponent form around1e21. So a row can disagree about spelling while agreeing about the number. Those rows say so, and check the value inside the exponent before they say it. - One seventh in base three. The exact answer repeats forever; your browser’s answer stops after thirty-seven digits, because a double always stops. The two are different numbers, and the row prints the distance. This is the cleanest thing to look at if you want to know where the two engines part company.
Refusing to read one meaning as another
The rule is that a numeral you meant one way must not be read another way, so everything a browser engine would guess at is handed back to you:
- Digits from another script. Arabic-Indic
١٢٣, superscript two, the vulgar fraction one half and the mathematical bold digits are all refused. This is measured, not assumed:Numberanswers not-a-number for every one of them, so the converter is no weaker here than the engine it is compared against. - An empty box.
Number("")is0. A blank field left in a form is a number nobody wrote, so the converter asks you to write one. - Two bases at once.
1e3is one thousand toNumberand four hundred and eighty-three toparseIntat base sixteen, because in base sixteeneis a digit. The converter readseas a digit or not at all, and refuses to guess which you meant. - A prefix that names a different base.
0b101in a box set to base sixteen: the prefix names its own base, and the converter will not decide between them. Note that the engines split here too -Numberreads0b101as five,parseIntat base two reads the zero, stops at theb, and answers zero. - Underscores, commas, spaces in the middle, a second point, a lone sign.
1_0is a separator for source code, not for text a program reads, andBigIntandNumberboth refuse it;parseIntanswers1by stopping. The converter refuses it too. - A base outside two to thirty-six. The alphabet in use has thirty-six single-digit symbols, so a base
needs a digit for every value below it. Base one is not a positional system, and
toStringthrowsRangeErrorfor both - which is why the base is refused before either engine runs. - Base sixty-four. Sixty-four is a way of writing bytes, not a way of writing a value; the tool for that is Base64 text.
- A fraction as bytes. A width holds whole numbers. The whole part goes to the byte table and the part after the point goes to the bases table, and the converter says which is which rather than picking one silently.
Refusals are counted, not dropped: the third table lists each thing stopped on, what it says instead, and how many times it came up.
Limits, and why they are that size
Twelve hundred digits in one numeral. Long division on a ratio of two arbitrary-precision integers costs time that grows with the square of the digit count, and a numeral past twelve hundred digits is a file to open rather than a box to read.
Ninety digits after the point when expanding a fraction. The repeating block of a fraction over d
is at most d-1 long, so ninety digits proves “this ends” outright and gives a long enough run to be
confident about “this repeats”. Where the search stopped, the cell says so rather than
claiming a block it did not find.
Three hundred rows in any one table, and twenty-four in the digit-by-digit ledger. The rest of the arithmetic is the same; the tables stop rather than filling the screen.
ASCII digits and ASCII letters only, which is a fact about the engines on the other side of the differential, not a shortage of ambition: the converter would rather refuse a digit it cannot name than accept one the browser it is compared against also refuses.
No Unicode names, no arbitrary precision on the browser side, no floating-point shortcuts. No data file is carried and no library is called. The claim is that everything printed here is either arithmetic you can repeat by hand from the tables, or your own browser’s answer quoted back at you.