Why parseInt loses your last digits
parseInt('deadbeefdeadbeef', 16) prints 16045690984833335000. The right answer is 16045690984833335023, and the value actually stored is 16045690984833335296, which is 273 too high. Nothing warns you: a number comes back, it looks the right size, and its last digits are invented.
The cause is the type, not the parser. A JavaScript Number is a float64, which carries 53 bits of integer precision, so every whole number above 9,007,199,254,740,991 rounds to the nearest value the format can hold. That ceiling sits right in the middle of the range people convert bases for: a 64-bit hash, a Snowflake or Twitter id, a memory address, a MAC address written as one number. All of them are past it.
This converter uses BigInt for every value it touches, in both directions. It has no upper bound, so a 512-bit key converts exactly, and the digits you get back are the digits that were there. If you are writing the conversion yourself, the fix is the same one: BigInt('0x' + hex) for the common bases, and a digit loop for the rest, since BigInt() only understands decimal and the three prefixed forms.
Two's complement, and why -1 is ffffffff
A negative number has no minus sign in a register. It has a bit pattern, and the convention every current CPU uses is two's complement: the top bit is worth minus its place value instead of plus. In 8 bits that makes the top bit worth -128, so 1111 1111 is -128 + 64 + 32 + 16 + 8 + 4 + 2 + 1, which is -1.
The useful consequence is that addition needs no special case. 255 + 1 overflows an 8-bit register to 0, and -1 + 1 is also 0, using the same adder and the same carry. It also explains the asymmetry in every signed range you have ever seen: 8 bits hold -128 to 127, not -127 to 127, because zero takes one of the positive slots.
The Unsigned and Signed rows above are two readings of one pattern. Nothing in the bits says which is right. The type in your code decides, and a mismatch between the two is how a file size arrives as 4,294,967,295 bytes or a temperature reads as 65,491 degrees.
Prefixes and where they hold
0x for hex, 0b for binary and 0o for octal are source-code notation, not part of the number. Paste one here with the matching base selected and it is stripped. Paste 0xff with decimal selected and the tool says so rather than guessing, because that particular guess has two plausible answers.
There is one case where a prefix is not a prefix. In base 16, 0b11 is four legal hex digits worth 2,833. Reading it as binary would return 3, an error of a factor of 900. So a prefix letter counts as a prefix only in bases where it is not also a digit, which is why 0x works in decimal and binary and means something else in base 36.
Watch out for the older octal form as well. A leading zero on its own, as in 0755, means octal in C and in older JavaScript but decimal in most other places. It is ambiguous enough that this tool treats it as an ordinary digit and leaves the base to the selector.
Common problems
- Leading zeros disappear. They carry no value, so
00ffandffare one number. Where the width matters, read it off the fixed-width panel instead, which pads to the register you picked. - A hash does not fit an integer. A SHA-256 digest is 256 bits. It converts exactly here, but no 64-bit column will hold it, and rounding it through a
Numberis the bug at the top of this page. - Base 36 is not base 16 with more letters in the same order. It uses 0 to 9 then a to z, so
zis 35 and10is 36. Short ids and URL slugs are often base 36 or base 62 for exactly that density. - Set-bit positions count from zero at the right. Bit 0 is the 1s place. Permission flags, feature masks and chmod bits are all read that way.
Frequently asked questions
What is the largest number this handles?
There is no ceiling. Conversion runs on BigInt, so a 200-digit value converts exactly, and the answer past 2^53 is right rather than rounded. That is the whole reason the page exists: the obvious implementation quietly loses precision long before it runs out of digits.
Why does base 36 stop there?
Because it runs out of symbols. Base 36 uses the ten digits plus the twenty-six letters, and there is no thirty-seventh character everyone agrees on. Base 62 and base 64 exist, but they need a stated alphabet, and different systems pick different ones.
How do I convert a negative number?
Type it with a minus sign for the plain conversion. For the bit pattern a machine would actually store, use the two's complement view and pick the register width, because -1 is ffffffff in 32 bits and ffffffffffffffff in 64.
Can it convert fractions?
No, integers only. Fractional conversion between bases is a different problem with its own rounding traps, and a tool that half-supported it would be worse than one that says so.
Nothing leaves this tab
The conversion runs in your browser. The value you type is never sent anywhere and never put in the URL. The base and register width are, so a link carries your settings and not your data. If you need the bytes of a string rather than the digits of a number, the text to binary converter is the tool for that.