Most people go through their entire programming career without thinking much about number systems. You write 255 and the computer knows what you mean. But then you encounter a hex color like #FF5733, a binary permission mask like 0b11101101, or an octal file permission like 0755, and suddenly you need to understand how numbers can be represented in different bases.
The good news is that all number systems follow the same logic. Once you understand how decimal works (which you already do intuitively), binary, hexadecimal, and octal are just the same concept with different base values. The patterns transfer directly.
How Number Bases Actually Work
In decimal (base 10), the number 347 means: 3 hundreds + 4 tens + 7 ones. Each position represents a power of 10. The rightmost digit is 10^0 (which is 1), the next is 10^1 (which is 10), the next is 10^2 (which is 100), and so on.
Binary (base 2) works identically, but each position represents a power of 2. The binary number 1101 means: 1 eight + 1 four + 0 twos + 1 one = 13 in decimal. The digits can only be 0 or 1.
Hexadecimal (base 16) uses powers of 16 and has 16 digits: 0-9 plus A-F (where A=10, B=11, C=12, D=13, E=14, F=15). The hex number 1A3 means: 1 two-hundred-fifty-six + 10 sixteens + 3 ones = 419 in decimal.
Octal (base 8) uses powers of 8 and digits 0-7. The octal number 755 means: 7 sixty-fours + 5 eights + 5 ones = 493 in decimal.
The Unit Converter handles conversions between these number bases instantly. Type a value in any base and see it in all others. This is faster than doing the arithmetic by hand, especially for large numbers.

Where Each Number System Is Used in Practice
Binary is the language of hardware. CPUs process binary instructions. Memory stores binary values. Network protocols transmit binary data. You encounter binary directly when working with bitwise operations, feature flags, permission masks, and low-level protocols.
A common use case is storing multiple boolean flags in a single integer. Instead of eight separate boolean fields, you use one byte where each bit represents a flag: 10110001 might mean "feature A on, feature B off, feature C on, feature D on, features E-G off, feature H on."
Hexadecimal is the human-readable representation of binary. Every hex digit maps to exactly 4 binary digits, which makes it a compact way to read binary values. The byte 11111111 in binary is simply FF in hex. You see hex everywhere: CSS colors (#FF5733), memory addresses (0x7fff5fbff8a0), MAC addresses (00:1A:2B:3C:4D:5E), and cryptographic hashes.
The Hash Generator produces output in hexadecimal format. SHA-256, MD5, and other hash algorithms all output binary data that gets displayed as hex strings for readability.
Octal is mostly a Unix relic. File permissions in Linux and macOS use octal notation: 755 means the owner can read, write, and execute; the group can read and execute; others can read and execute. Each digit represents three permission bits (read=4, write=2, execute=1), and three bits map perfectly to one octal digit.
**Binary** is the language of hardware.
Converting Between Number Systems by Hand
Decimal to binary: Divide by 2 repeatedly and collect the remainders. 42 divided by 2 is 21 remainder 0. 21 divided by 2 is 10 remainder 1. 10 divided by 2 is 5 remainder 0. 5 divided by 2 is 2 remainder 1. 2 divided by 2 is 1 remainder 0. 1 divided by 2 is 0 remainder 1. Read the remainders bottom-to-top: 101010.
Binary to hex: Group binary digits into sets of 4 from right to left. 101010 becomes 0010 1010, which is 2A in hex (0010=2, 1010=A).
Hex to binary: Replace each hex digit with its 4-bit binary equivalent. FF becomes 1111 1111.
Decimal to hex: Divide by 16 repeatedly. 255 divided by 16 is 15 remainder 15. 15 divided by 16 is 0 remainder 15. Two remainders of 15 = FF.
These manual conversions are useful for understanding, but nobody does them regularly. For practical work, use a converter tool or your programming language's built-in functions. In JavaScript: (255).toString(16) gives 'ff', and parseInt('ff', 16) gives 255.
Bitwise Operations Explained Simply
Bitwise operations manipulate individual bits within a number. They are fast (single CPU instruction) and useful for specific patterns.
AND (&): Both bits must be 1. Used for masking. 1010 & 1100 = 1000. In practice, flags & PERMISSION_READ checks if the read permission bit is set.
OR (|): Either bit can be 1. Used for combining flags. 1010 | 0101 = 1111. Use flags | PERMISSION_WRITE to add the write permission.
XOR (^): Bits must be different. Used for toggling and simple encryption. 1010 ^ 1100 = 0110. XOR with the same value twice returns the original: a ^ b ^ b = a.
NOT (~): Flips all bits. ~1010 = 0101. Used for creating inverse masks.
Left shift (<<): Moves bits left, filling with zeros. 1 << 3 = 1000 (which is 8). Left shifting by N is the same as multiplying by 2^N.
Right shift (>>): Moves bits right. 1000 >> 2 = 10 (which is 2). Right shifting by N is the same as dividing by 2^N (integer division).
These operations show up in performance-critical code, graphics programming, network protocols, and embedded systems. For most web development, you encounter them mainly in permission systems and feature flags.

Encoding vs Number Systems
Number systems and encoding are related but different concepts. A number system is a way to represent numeric values. An encoding is a way to represent arbitrary data (text, images, binary files) as a sequence of characters.
Base64 is an encoding, not a number system. It converts binary data into a string of 64 ASCII characters (A-Z, a-z, 0-9, +, /). You use it to embed binary data in text-based formats like JSON, email, and URLs. The Base64 Encoder converts text and files to and from Base64 format.
Hex encoding is technically a number system representation, but it is often used as an encoding format. When you see a SHA-256 hash displayed as a 64-character hex string, that is binary data (32 bytes) encoded as hexadecimal text for display.
The practical difference: number system conversions preserve numeric meaning (the hex value FF equals the decimal value 255). Encodings preserve data content (Base64 encoding of "Hello" lets you transmit those bytes through a text channel, but the encoded string SGVsbG8= has no numeric relationship to the original text).
Common Pitfalls and Debugging Tips
Leading zeros change the base in some languages. In JavaScript (old style) and C, a number starting with 0 is interpreted as octal. Writing 010 gives you 8, not 10. Modern JavaScript uses 0o10 for octal to avoid this confusion, but older codebases still have this bug lurking.
Hex colors and hex numbers use the same digits but mean different things. The CSS color #FF0000 is not the number 16711680 to CSS. It is three separate byte values (FF, 00, 00) representing red, green, and blue channels. Treating them as one large number gives misleading results.
Signed vs unsigned matters. In a signed 8-bit integer, 11111111 is -1 (two's complement). In an unsigned 8-bit integer, 11111111 is 255. The bits are identical. The interpretation depends on whether the number type is signed or unsigned. This is a common source of bugs in languages like C and Java.
Integer overflow is real. A 32-bit unsigned integer maxes out at 4,294,967,295 (or FFFFFFFF in hex). Adding 1 wraps around to 0. This is not a bug in your code. It is how fixed-width integer arithmetic works in hardware. JavaScript avoids this with its arbitrary-precision BigInt type, but most languages use fixed-width integers by default.
**Leading zeros change the base in some languages.** In JavaScript (old style) and C, a number starting with `0` is interpreted as octal.
FAQ
Why do programmers use hexadecimal instead of just writing binary?
Readability. A 32-bit binary number like 11111111000000001010101101011010 is unreadable. The same value in hex is FF00AB5A, which is eight characters that experienced developers can parse at a glance. Each hex digit maps to exactly 4 bits, so the conversion is trivial.
Why is octal still used for file permissions?
Historical convention. Unix file permissions use 3 groups of 3 bits (owner, group, others), and 3 bits map perfectly to one octal digit (0-7). The notation 755 is shorter and more familiar to system administrators than the binary equivalent 111 101 101 or the symbolic notation rwxr-xr-x. It stuck because it works well for this specific use case.
Can I use binary or hex directly in my programming language?
Most modern languages support binary and hex literals. In JavaScript: 0b1010 (binary, equals 10) and 0xFF (hex, equals 255). In Python: 0b1010 and 0xFF. In C/C++/Java/Rust: same syntax. Prefix 0b for binary, 0x for hex, 0o for octal.
What is the largest number a single byte can hold?
255 in decimal, FF in hex, 11111111 in binary, 377 in octal. A byte is 8 bits, and 2^8 minus 1 equals 255. This is why RGB color channels (each one byte) range from 0 to 255.
JSON Guide: Format, Validate, and Convert JSON Files
JSON guide for developers: syntax rules, common parse errors, formatting and schema validation, plus how to convert between JSON and CSV files.
Base64, URL Encoding & HTML Entities Explained
Encode and decode Base64, URLs, and HTML entities in your browser. Learn when to use each format, with clear examples and free converter tools.
Regular Expressions for Beginners: A Practical Guide
Learn regular expressions from scratch: basic syntax, character classes, quantifiers, and practical patterns for matching emails, URLs, and phone numbers.
