When converting binary to decimal, the exact answer depends entirely on your data type assumption. For the 8-bit binary query values 10110101 and 11001010, the direct unsigned decimal answers are 181 and 202. However, if your microcontroller register interprets these as signed 8-bit integers (Two's complement), the answers immediately shift to -75 and -54. You cannot correctly parse a raw binary dump from a sensor or logic analyzer without first fixing the bit-width, sign, and encoding assumptions.
The Core Math: Formula and Substitution
The fundamental formula for converting an unsigned binary number to decimal is the sum of each bit multiplied by 2 raised to the power of its positional index (starting from 0 on the far right):
Decimal = Σ (bit_n × 2^n)
Let's substitute the exact values from our primary query, 10110101, into the formula:
- Bit 7 (MSB): 1 × 2^7 = 128
- Bit 6: 0 × 2^6 = 0
- Bit 5: 1 × 2^5 = 32
- Bit 4: 1 × 2^4 = 16
- Bit 3: 0 × 2^3 = 0
- Bit 2: 1 × 2^2 = 4
- Bit 1: 0 × 2^1 = 0
- Bit 0 (LSB): 1 × 2^0 = 1
Summing these yields: 128 + 32 + 16 + 4 + 1 = 181. For a deeper dive into base-2 mathematics, Math is Fun's binary guide provides excellent foundational practice.
Neighboring Values Table (±20% Range of 181)
When debugging I2C or SPI buses, you rarely see just one isolated value. Below is a reference table showing the ±20% neighborhood around our target value of 181 (spanning roughly 145 to 217), which helps identify off-by-one errors or slight sensor drift.
| Decimal Target | 8-Bit Binary | Hex Equivalent | Deviation from 181 |
|---|---|---|---|
| 145 | 10010001 | 0x91 | -20% |
| 163 | 10100011 | 0xA3 | -10% |
| 181 | 10110101 | 0xB5 | Baseline |
| 199 | 11000111 | 0xC7 | +10% |
| 217 | 11011001 | 0xD9 | +20% |
How Bit-Width and Sign Assumptions Shift the Decimal
Just as AC power calculations shift drastically depending on whether you are measuring 120V single-phase or 208V 3-phase, binary conversion shifts dramatically based on register width and signedness. What assumption fixes the answer? The variable type declared in your firmware (e.g., uint8_t vs int8_t) and the byte-order (endianness) of the sensor.
If you read 10110101 from an 8-bit register, it is 181 (unsigned) or -75 (signed). But how does the answer shift for 8-bit vs 16-bit vs 32-bit registers? If that same 8-bit value is placed into a 16-bit unsigned integer (uint16_t), it is zero-padded to 0000000010110101 and remains 181. If it is placed into a 16-bit signed integer (int16_t), the compiler performs sign extension, copying the MSB (1) into the upper byte, resulting in 1111111110110101, which still equals -75. However, if you accidentally read two 8-bit sensor registers in the wrong endianness order (e.g., reading 0xB5 then 0xCA as 0xB5CA instead of 0xCAB5), your decimal output shifts from 46538 to 51893.
| Raw Binary (Hex) | 8-Bit Unsigned (uint8_t) | 8-Bit Signed (int8_t) | 16-Bit Sign-Extended (int16_t) | Common Embedded Use Case |
|---|---|---|---|---|
| 0xB5 (10110101) | 181 | -75 | -75 | GPIO pin states, PWM duty cycles |
| 0xCA (11001010) | 202 | -54 | -54 | ADC raw 8-bit readings |
| 0x7F (01111111) | 127 | 127 | 127 | Maximum positive signed 8-bit |
| 0x80 (10000000) | 128 | -128 | -128 | Minimum negative signed 8-bit |
| 0xFF (11111111) | 255 | -1 | -1 | Error flags, blanking unprogrammed EEPROM |
For exact C++ data type boundaries and overflow behaviors, refer to the C++ reference on fundamental types.
When Raw Binary-to-Decimal Conversion is Meaningless
There are specific scenarios in digital electronics where applying the standard base-2 summation formula yields a mathematically correct but practically meaningless decimal number. Recognizing these prevents hours of debugging.
1. IEEE 754 Floating-Point Numbers
If your ESP32 receives a 32-bit payload over MQTT representing a temperature sensor reading, and the binary string is 01000000010010010000111111011011, converting this as a raw integer yields 1,078,525,915. This number is useless. The binary is actually an IEEE 754 single-precision float encoding the decimal value 3.14159. The bits are divided into a 1-bit sign, 8-bit exponent, and 23-bit mantissa. You must cast the raw bytes to a float in your code rather than parsing them as an integer.
2. Binary-Coded Decimal (BCD)
Real-time clock (RTC) modules like the DS3231 store time in BCD, not pure binary. In BCD, each 4-bit nibble represents a single decimal digit (0-9). If you read the seconds register and get 01011001, a raw binary conversion gives 89. But 89 seconds is impossible. In BCD, the upper nibble 0101 is 5, and the lower nibble 1001 is 9, meaning the actual time is 59 seconds. Furthermore, a binary value like 10110101 is entirely invalid in BCD because the nibble 1011 (11) exceeds the maximum digit of 9.
3. ASCII Encoded Text
When reading from a serial UART buffer, the binary 01000001 converts to 65 in decimal. While mathematically true, in the context of an ASCII serial stream, 65 represents the capital letter 'A'. Treating serial text payloads as raw numeric integers will corrupt your data parsing logic.
Frequently Asked Questions
Why does my Arduino print 65461 instead of -75 for a 16-bit sensor reading?
You declared your variable as an unsigned int (or uint16_t). The binary 1111111110110101 equals 65461 when treated as strictly positive. Change your variable declaration to int16_t to force the compiler to interpret the MSB as a negative sign bit via Two's complement.
How do I handle endianness when converting 16-bit I2C registers?
Most Bosch sensors (like the BME280) are little-endian, meaning the Least Significant Byte (LSB) arrives first. If you read 0xB5 then 0xCA, the 16-bit hex value is 0xCAB5 (51893 decimal). If you mistakenly concatenate them in the order received (0xB5CA), you will get 46538. Always check the sensor datasheet's 'Data Format' section.
Is there a quick bitwise trick to convert BCD to decimal in C++?
Yes. If val is your 8-bit BCD variable, use: decimal = (val >> 4) * 10 + (val & 0x0F);. This shifts the upper nibble to the right, multiplies it by 10, and adds the lower nibble, bypassing raw binary conversion entirely.






