fileformer
search⌘KtranslateENexpand_moreupload_fileConvert
Converters8 file families · 44 direct conversions
What changes in a conversionarrow_forward
home/developer-tools/number-base-converter

One number, four ways to write it.

Type in any box and the others update: decimal, hexadecimal, binary and octal. Or flip individual bits below and watch the value change. Switch on signed mode to see how negative numbers are stored.

decimalbase 10
unsigned 16-bit
hexadecimalbase 16
0x
2 bytes
binarybase 2
0b
11 significant bits
octalbase 8
0o
3 bits per digit
8-bit16-bit32-bit64-bit
exposure_plus_1unsignedNOT<<1>>1−x
02^1502^1402^1302^1202^111102415121256
byte 10x07
112816413201618041201
byte 00xEA
range0 to 65,535bits set8 of 16power of twonoas ASCII-
~/how-it-adds-up

Every base works the same way. Only the step size changes.

In decimal each position is worth ten times the one to its right. In hex it's sixteen, in binary two. Here is your current number broken into positions, with the sum that gets back to it.

decimalhexbinaryoctal
7× 16^21,792
E× 16^1224
A× 16^010
7×16^2 + E×16^1 + A×16^0 = 2,026Hex digits A: F stand for 10-15, so a single character covers a whole four-bit group.
~/where-you-see-them

Why programmers bother with hex and octal.

One hex digit is exactly four bits and one octal digit exactly three, so they're compact ways to write binary. Two everyday examples, both working.

A hex colour is three bytes#4f46e5
R4F · 79
G46 · 70
BE5 · 229
Each pair of hex digits is one byte, 0-255, for red, green and blue. That's why colours come in steps of 256 per channel.
File permissions are three octal digitschmod 755
read 4write 2run 1=
ownerrwx7
groupr-x5
othersr-x5
Shown by ls -l as rwxr-xr-x. The usual setting for programs and folders: everyone can read and run, only you can change it.
~/bytes-in-memory

The same number, as the bytes a computer actually stores.

This is the number from the converter above, at its chosen width. Your browser writes it into memory with a DataView in both byte orders, then runs it through the bitwise operators. JavaScript's operators quietly cut every number to 32 bits; only BigInt keeps all 64.

Big-endiannetwork byte order
+007+1EA
Most significant byte first, the way the number is written. TCP/IP headers, PNG, JPEG and Java’s DataOutputStream use it.
Little-endianx86, ARM, RISC-V
+0EA+107
Least significant byte first. This device is little-endian, so a Uint16Array holding this value stores exactly these bytes. WAV, ZIP, BMP and USB use it.
SECOND OPERAND · decimal or 0x…
0xFF1433-1
Shift operations use this number as the shift count. JavaScript only looks at its lowest 5 bits, so shifting by 33 is a shift by 1.
expressionJavaScript Number (32-bit)BigInt, at the chosen width
a & b23400000000 00000000 00000000 111010102340x00EA
a | b204700000000 00000000 00000111 1111111120470x07FF
a ^ b181300000000 00000000 00000111 0001010118130x0715
~a-202711111111 11111111 11111000 00010101635090xF815
a << b000000000 00000000 00000000 0000000000x0000
a >> b000000000 00000000 00000000 0000000000x0000
a >>> b000000000 00000000 00000000 0000000000x0000
a | 0202600000000 00000000 00000111 1110101020260x07EA
warning1 of 8 rows differ (highlighted). JavaScript converts both operands to 32-bit signed integers before any bitwise operation. >>> then reinterprets the result as unsigned. BigInt keeps the full 16 bits, wrapped to the chosen width.
~/how-bases-really-convert

Divide, keep the remainder, repeat. And why parseInt surprises people.

Converting to any base is repeated division: the remainders, read from bottom to top, are the digits. Pick a base from 2 to 36 to see every step for the converter's number. Then see how JavaScript's built-in parsers read the same text in different ways.

TARGET BASEbase 7
2026 ÷ 7=289r 3
289 ÷ 7=41r 2
41 ÷ 7=5r 6
5 ÷ 7=0r 5
REMAINDERS, BOTTOM TO TOP · checked against toString(7)5623matches toString(7)
0x1F081e30b101 42px90071992547409930.0000005null
callresultwhy
parseInt(s)31Reads leading digits and stops at the first character it can’t use. A leading 0x switches to hex; nothing else switches base.
parseInt(s, 10)0Always base 10, so 0x1F gives 0 and 08 gives 8. Always pass a radix.
parseInt(s, 16)31Hex digits only. Accepts an optional 0x prefix.
parseInt(s, 2)0Binary digits only. 0b is not a recognised prefix, so 0b101 gives 0.
Number(s)31The whole string must be a valid numeric literal: 0x, 0o and 0b work, trailing text gives NaN, empty or null gives 0.
parseFloat(s)0Decimal only, but reads exponents such as 1e3.
BigInt(s)31nExact integers of any size. Throws on fractions, exponents and trailing text.
+s === parseInt(s)trueWhether the two most common idioms agree on this input.
~/reference

Integer types, their limits, and what happens one past them.

Every limit below was computed with BigInt when the page loaded. The last column shows what the maximum plus one wraps to in two's complement, which is what C, Java, Rust in release builds and most hardware do.

typeminimummaximummax + 1 wraps tonames in C · Java · Rust
int8-128127-128int8_t · byte · i8
uint802550uint8_t · char · u8
int16-32,76832,767-32,768int16_t · short · i16
uint16065,5350uint16_t · char (16-bit only) · u16
int32-2,147,483,6482,147,483,647-2,147,483,648int32_t · int · i32
uint3204,294,967,2950uint32_t ·: · u32
int64-9,223,372,036,854,775,8089,223,372,036,854,775,807-9,223,372,036,854,775,808int64_t · long · i64
uint64018,446,744,073,709,551,6150uint64_t ·: · u64
int128-170,141,183,460,469,231,731,687,303,715,884,105,728170,141,183,460,469,231,731,687,303,715,884,105,727-170,141,183,460,469,231,731,687,303,715,884,105,728__int128 ·: · i128
uint1280340,282,366,920,938,463,463,374,607,431,768,211,4550__int128 ·: · u128

Writing other bases in code

languagehexoctalbinaryseparatorparse a string
JavaScript0x1F0o170b10111_000_000parseInt(s, 16)
Python0x1F0o170b10111_000_000int(s, 16)
C, C++0x1F0170b1011 (C23, C++14)1'000'000 (C++14, C23)strtol(s, NULL, 16)
Java0x1F0170b10111_000_000Integer.parseInt(s, 16)
C#0x1F-0b10111_000_000Convert.ToInt32(s, 16)
Go0x1F0o17 or 0170b10111_000_000strconv.ParseInt(s, 16, 64)
Rust0x1F0o170b10111_000_000i64::from_str_radix(s, 16)
SQL (PostgreSQL 16)0x1F0o170b10111_000_000x'1F'::int
Checked in this browser: Number() reads 0x1F, 0o17, 0b1011 correctly. Numeric separators like 1_000_000 are valid in JavaScript source code but not in strings, so Number("1_000_000") is NaN. A leading 0 in C means octal, so 017 is 15, a classic bug when padding numbers with zeros.

From counting rods to BigInt

c. 1800 BCBabylonian base 60Cuneiform tablets record a positional system in base 60, which survives in minutes, seconds and degrees.
c. 628Zero as a numberBrahmagupta sets out rules for arithmetic with zero, the digit place value needs.
1703Leibniz and binaryGottfried Leibniz publishes his account of binary arithmetic.
1937Shannon’s thesisClaude Shannon shows Boolean algebra can describe relay switching circuits.
1945Two’s complementVon Neumann’s EDVAC report proposes the representation almost every CPU now uses for negative integers.
1964IBM System/360Popularises the 8-bit byte and hexadecimal dumps.
1980Endianness namedDanny Cohen’s “On Holy Wars and a Plea for Peace” borrows big-endian and little-endian from Gulliver’s Travels.
2020BigIntES2020 adds arbitrary-precision integers to JavaScript.