When you move from wiring physical circuits to programming microcontrollers, the multimeter is replaced by the logic analyzer, and voltage levels are abstracted into ones and zeros. A numbers in binary chart is your foundational translation tool. It maps base-2 positional weights to their decimal and hexadecimal equivalents, allowing you to manipulate hardware registers, configure pin modes, and execute bitmasking operations without relying on software calculators. The direct answer for embedded engineers: you need the bit-weight column ($2^n$) to calculate decimal values, and the hex multiplier column to write clean C++ register commands.

The Complete Binary Numbers Chart (Base-2 Positional Reference)

How to read this table: This chart is based on standard positional numeral system mathematics and aligns with the binary prefix definitions outlined in ISO/IEC 80000-13 and NIST guidelines. The Bit Position (n) column represents the physical pin or register bit index, starting at 0 (the Least Significant Bit, or LSB). The Binary Weight column shows the mathematical multiplier ($2^n$). The Decimal Value is the base-10 equivalent you will see when printing variables to the Serial Monitor. Bookmark-friendly quick-jump rows for standard byte boundaries (8-bit, 16-bit, 32-bit) are highlighted in bold.

Bit Position (n)Binary Weight ($2^n$)Hex MultiplierDecimal ValueRegister Boundary
0$2^0$0x011LSB
1$2^1$0x022-
2$2^2$0x044-
3$2^3$0x088-
4$2^4$0x1016-
5$2^5$0x2032-
6$2^6$0x4064-
7$2^7$0x801288-bit MSB (AVR)
8$2^8$0x100256Byte 1 Start
9$2^9$0x200512-
10$2^{10}$0x4001,024-
11$2^{11}$0x8002,048-
12$2^{12}$0x10004,096-
13$2^{13}$0x20008,192-
14$2^{14}$0x400016,384-
15$2^{15}$0x800032,76816-bit MSB
16$2^{16}$0x1000065,536Byte 2 Start
17$2^{17}$0x20000131,072-
18$2^{18}$0x40000262,144-
19$2^{19}$0x80000524,288-
20$2^{20}$0x1000001,048,576-
21$2^{21}$0x2000002,097,152-
22$2^{22}$0x4000004,194,304-
23$2^{23}$0x8000008,388,60824-bit Boundary
24$2^{24}$0x100000016,777,216Byte 3 Start
25$2^{25}$0x200000033,554,432-
26$2^{26}$0x400000067,108,864-
27$2^{27}$0x8000000134,217,728-
28$2^{28}$0x10000000268,435,456-
29$2^{29}$0x20000000536,870,912-
30$2^{30}$0x400000001,073,741,824-
31$2^{31}$0x800000002,147,483,64832-bit MSB (ESP32/ARM)
Bench Tip: When writing C++ for an ESP32, always use the 0x hex multipliers for register masking (e.g., REG_WRITE(GPIO_OUT_W1TS_REG, 0x04) to set Bit 2 high). Using decimal values for bits above 15 leads to unreadable code and transcription errors.

Applying the Chart to Microcontroller Registers

Which Column Applies to Your Installation?

The 'Bit Position' column you use depends entirely on your microcontroller's architecture. If you are programming an 8-bit ATmega328P (Arduino Uno/Nano), your hardware registers (like PORTB or DDRC) are only 8 bits wide. You will only ever reference Bit Positions 0 through 7. Attempting to write a '1' to Bit Position 8 on an 8-bit register results in the bit being truncated; the hardware simply ignores it.

Conversely, if you are working with a 32-bit ESP32 (Xtensa LX6 architecture), the ESP32 Technical Reference Manual defines GPIO registers like GPIO_OUT_REG as full 32-bit integers. Here, you utilize the chart all the way up to Bit Position 31. However, a critical hardware caveat: while the register is 32 bits, the ESP32 only has physical GPIO pins mapped up to bit 39, and pins 34-39 are input-only. Writing a '1' to Bit 34 in the output register will compile, but it will not drive a physical pin high.

How Bit-Shifting and Overflow Modify the Base Value (The Binary 'Derating')

In electrical wire ampacity charts, 'derating' rows reduce the base current capacity based on temperature or conduit fill. In binary logic, the equivalent modification to your base value occurs through bit-shifting and overflow.

  • Left Shift (<<): Shifting a binary number left by $n$ positions multiplies the base decimal value by $2^n$. For example, 1 << 3 moves the '1' from Bit 0 to Bit 3, changing the decimal value from 1 to 8.
  • Right Shift (>>): Shifting right divides the base value by 2 per shift, dropping any remainders (acting as a fast integer division).
  • Overflow (The Binary Derating Limit): If you left-shift a value past the Most Significant Bit (MSB) of your register width, the bit 'falls off' the edge. Shifting an 8-bit value of 128 (Bit 7) left by one position results in 0, not 256. The register overflows, and the base value collapses to zero. Always cast to a wider integer type (e.g., uint32_t) before shifting if your math approaches the MSB boundary.

What This Binary Chart Cannot Tell You

While this chart perfectly maps mathematical weights, it lacks the physical and architectural context required to debug hardware. Here is what the table hides:

1. Endianness (Byte Order): The chart assumes a purely mathematical left-to-right reading. But when a 32-bit integer is stored in the ESP32's physical SRAM, it uses Little-Endian format. The Least Significant Byte (Bits 0-7) is stored at the lowest memory address. If you are reading raw memory dumps via a logic analyzer or JTAG, the bytes will appear reversed compared to how you write them in code.

2. Signed vs. Unsigned Interpretation (Two's Complement): The chart shows Bit 31 as $+2,147,483,648$. However, if your C++ variable is declared as a signed int32_t rather than an unsigned uint32_t, Bit 31 becomes the sign bit. A '1' in Bit 31 no longer means two billion; it flips the entire number into the negative spectrum (specifically, $-2,147,483,648$). Always use uint32_t for hardware register manipulation to prevent the compiler from misinterpreting your bitmask as a negative number.

3. Physical Voltage Thresholds ($V_{IH}$ and $V_{IL}$): A binary '1' is a mathematical abstraction. On the bench, a '1' is a voltage. For a 5V Arduino Uno, any voltage above 3.0V ($0.6 \times V_{CC}$) is read as a '1'. For a 3.3V ESP32, the threshold drops to roughly 2.47V ($0.75 \times V_{DD}$). If your sensor outputs a 2.0V high signal, the binary chart says it's a '1', but the ESP32's silicon will read it as a '0' due to the physical voltage threshold.

Frequently Asked Questions About Numbers in Binary Charts

How do I read negative numbers in a binary chart?

Microcontrollers use a system called Two's Complement to represent negative numbers. To find the binary equivalent of a negative decimal (e.g., -5 in an 8-bit register), first look up the positive number (5 = 00000101). Next, invert every bit (change 1s to 0s and 0s to 1s) to get 11111010. Finally, add 1 to the result. The binary representation of -5 is 11111011. Notice that the MSB (Bit 7) is now a '1', which is the universal indicator of a negative signed integer in binary.

Why does my ESP32 binary chart lookup show different hex values than my Arduino?

This discrepancy is almost always caused by register width and default variable types. On an 8-bit Arduino, the default int is 16 bits, and bitwise operations on standard integers are truncated at 16 bits. On the 32-bit ESP32, the default int is 32 bits. If you write ~0 (bitwise NOT of zero) on an Arduino, you get 0xFFFF. On an ESP32, ~0 yields 0xFFFFFFFF. Always explicitly define your variable widths using stdint.h types like uint8_t, uint16_t, or uint32_t to ensure your hex values match the chart regardless of the board.

What is the fastest way to convert a decimal number to binary without a chart?

Use the 'subtract highest bit' method. Let's convert decimal 165. Look at the chart: the highest bit weight that fits into 165 is 128 (Bit 7). Write a '1' for Bit 7, and subtract 128 from 165, leaving 37. The next highest bit that fits into 37 is 32 (Bit 5). Write a '1' for Bit 5, subtract 32, leaving 5. Bit 2 (4) and Bit 0 (1) make up the remaining 5. Filling in the zeros for the skipped bits, you get 10100101. With practice, this is faster than repeatedly dividing by two.

How do bitwise AND/OR operations use this binary chart?

Bitwise operations use the chart to create 'masks'. If you want to check if Bit 3 is high in a sensor reading, you use a Bitwise AND (&) with the decimal value 8 (from the chart: $2^3 = 8$). The code if (sensorRead & 0x08) forces all bits except Bit 3 to zero. If Bit 3 was a '1', the result is non-zero (true). If you want to force Bit 3 high without altering the other pins, you use a Bitwise OR (|) with 8: register = register | 0x08;. The chart provides the exact decimal or hex 'key' needed to unlock specific bits without disturbing the rest of the byte.