Negative 2 in binary is represented using two's complement notation, where you invert the bits of positive 2 and add 1, yielding a sequence ending in 1110 (like 1111 1110 in an 8-bit register). When you are writing firmware for an ESP32 or wiring up a quadrature encoder, understanding exactly how the silicon interprets that minus sign is the difference between a smoothly tracking motor and a runaway PID loop that fries your H-bridge.

The Direct Answer: Binary Values for Negative 2

Microcontrollers do not have a dedicated "minus" symbol in their registers. Instead, they rely on the most significant bit (MSB) to indicate sign, and two's complement math to handle arithmetic seamlessly. The exact binary string for negative 2 depends entirely on the width of the register or data type you are using.

Quick Reference: Negative 2 Across Register Widths
  • 8-bit (int8_t): 1111 1110 (Hex 0xFE)
  • 16-bit (int16_t): 1111 1111 1111 1110 (Hex 0xFFFE)
  • 32-bit (int32_t): 1111...1111 1110 (Hex 0xFFFFFFFE)

In every case, the least significant bits are 1110, and all higher bits are padded with 1s. This padding is what allows the processor's Arithmetic Logic Unit (ALU) to add positive and negative numbers using the exact same hardware adder circuits without needing special subtraction logic.

The Math: A Worked Two's Complement Example

To understand why the binary for -2 looks the way it does, let's walk through the exact calculation for an 8-bit system. This is the same process the compiler executes when you assign int8_t x = -2;.

  1. Start with the positive value: Positive 2 in 8-bit binary is 0000 0010.
  2. Invert all bits (Bitwise NOT): Flip every 0 to 1, and every 1 to 0. This gives 1111 1101. (In C/C++, this is the ~2 operation).
  3. Add 1 to the result: 1111 1101 + 0000 0001 = 1111 1110.

The final result is 1111 1110. To verify this works, add positive 2 (0000 0010) and negative 2 (1111 1110) together using standard binary addition:

  0000 0010  (+2)
+ 1111 1110  (-2)
-----------------
1 0000 0000  (0, with a 9th-bit carry-out that is discarded in 8-bit math)

The carry-out bit is simply dropped because the register is only 8 bits wide, leaving exactly 0000 0000 (zero). This elegant wrap-around behavior is why two's complement is the universal standard for signed integers in modern computing.

Where You Meet This in Practice (And Why It Breaks Circuits)

Abstract math becomes a physical problem when you interface with real-world sensors and actuators. The most common point of failure is misinterpreting signed binary data as unsigned.

Real-World Failure Mode: The AS5600 Encoder Wrap-Around

Suppose you are using an AS5600 magnetic rotary encoder configured for 256 steps per revolution (8-bit resolution) to track a motor shaft. The motor is at position 0, and you command it to reverse by 2 steps. The physical position is now -2.

If your firmware reads this into an unsigned 8-bit integer (uint8_t), the microcontroller reads the raw binary 1111 1110 and interprets it as positive 254. Your PID control loop calculates an error of +254 steps, assumes the motor is almost a full rotation behind target, and slams the PWM duty cycle to 100%. The motor violently jerks forward, potentially stripping gears or triggering an overcurrent fault on your motor driver.

This is what changes in a real installation: a single missing minus sign in your variable declaration transforms a minor backward adjustment into a maximum-power forward command. Always match your variable's signedness to the physical reality of the sensor data.

Sign-Magnitude vs. Two's Complement: The Common Confusion

The most frequent mistake hobbyists make when manually converting negative numbers is assuming the MSB acts purely as a "minus sign" while the rest of the bits remain identical to the positive number. This is called sign-magnitude representation.

In sign-magnitude, negative 2 would be written as 1000 0010 (a 1 in the sign bit, followed by positive 2). While this makes intuitive sense to humans reading a screen, hardware designers abandoned it decades ago. Sign-magnitude creates two distinct binary representations for zero (0000 0000 for +0, and 1000 0000 for -0) and requires complex, slow logic gates to perform addition and subtraction.

Two's complement guarantees a single, unique zero and allows the ALU to use identical addition circuits for both positive and negative numbers. If you are manually inspecting a logic analyzer trace or a hex dump from an I2C sensor, remember that 1000 0010 is actually -126 in two's complement, not -2.

Decision Tree: Picking the Right Integer Type in Embedded C

Choosing the correct data type prevents binary wrap-around errors and ensures your bitwise operations behave predictably. Use this decision path to select your variable type in Arduino, ESP-IDF, or standard C/C++ environments.

Scenario Physical Constraint Required Data Type
Reading absolute limits (e.g., PWM duty cycle, ADC raw values) Value can never drop below 0 uint8_t or uint16_t
Tracking relative movement, deltas, or offsets (e.g., encoder ticks, joystick axes) Value frequently crosses zero into negatives int16_t or int32_t
Timestamps and uptime tracking (e.g., millis()) Monotonically increasing, rolls over at max limit uint32_t
Bitmasking and hardware register manipulation Sign bit interferes with logical shifts uint8_t / uint32_t
The Default Pick: Stop using the bare int keyword. The size of a bare int changes depending on the architecture (16-bit on AVR Arduinos, 32-bit on ESP32 and ARM Cortex boards). Always include <stdint.h> and explicitly declare int16_t for general sensor deltas and relative measurements. It guarantees 16 bits of width, safely holding values from -32,768 to 32,767 across every microcontroller you will ever program.

Frequently Asked Questions

What happens if I right-shift a negative binary number?

In C and C++, right-shifting a signed negative integer (e.g., -2 >> 1) performs an arithmetic shift. The processor fills the vacated MSB with 1s to preserve the negative sign. So, 1111 1110 (-2) shifted right by 1 becomes 1111 1111 (-1). If you cast it to an unsigned type first ((uint8_t)-2 >> 1), it performs a logical shift, padding with 0s, resulting in 0111 1111 (127). This distinction causes massive bugs in digital filter implementations.

How do I print the binary representation of -2 in the Arduino Serial Monitor?

The standard Serial.print(val, BIN) function struggles with negative numbers, often printing them as 32-bit strings or failing to pad correctly. To view the exact 8-bit two's complement binary of -2, cast it to a byte and use a bitwise mask: Serial.println((byte)-2 & 0xFF, BIN);. This forces the compiler to evaluate the 8-bit boundary and prints 11111110.

Does two's complement apply to floating-point numbers?

No. Floating-point numbers (like float or double) use the IEEE 754 standard, which relies on a dedicated sign bit, an exponent, and a mantissa. Two's complement is strictly for signed integer arithmetic. If you are doing high-speed PID math on an ESP32, stick to scaled integers (e.g., multiplying by 1000) to avoid the overhead of floating-point emulation on cores without dedicated FPUs.

For further reading on standard integer widths and hardware-level type definitions, consult the cppreference documentation for stdint.h and the Arduino Language Reference for data types.