Number Systems and Binary Arithmetic for Digital Electronics

Every digital circuit, from a simple counter to a 64-bit processor, works on numbers stored as patterns of 0s and 1s. Before you can design adders, read a microcontroller register map or debug a Verilog simulation, you need to move comfortably between binary, octal, decimal and hexadecimal, and you need to know how negative numbers are stored. This tutorial covers positional number systems, conversions, signed representations, 2's complement arithmetic, overflow detection and BCD, with worked examples you can check by hand.

Positional Number Systems

In a positional system with base (radix) r, each digit is multiplied by a power of r that depends on its position. The rightmost integer digit has weight r^0, the next r^1 and so on, while digits after the radix point have weights r^-1, r^-2 and so on. A digit can take values from 0 to r-1.

N = d(n-1)*r^(n-1) + ... + d1*r^1 + d0*r^0 + d(-1)*r^(-1) + ...

Example: (1011.01)2 = 1*8 + 0*4 + 1*2 + 1*1 + 0*0.5 + 1*0.25 = (11.25)10
SystemBaseDigitsWhere you meet it
Binary20, 1Logic levels, registers, bus signals
Octal80 to 7Older minicomputers, Unix file permissions
Decimal100 to 9Human input and display
Hexadecimal160 to 9, A to FMemory addresses, register values, colour codes

Converting Between Bases

Decimal to binary

For the integer part, divide repeatedly by 2 and collect the remainders from bottom to top. For the fractional part, multiply repeatedly by 2 and collect the integer carries from top to bottom. Some decimal fractions, such as 0.1, never terminate in binary, which is why floating-point values like 0.1 cannot be stored exactly.

Convert (45.375)10 to binary

Integer part           Fraction part
45 / 2 = 22  r 1       0.375 * 2 = 0.75  -> 0
22 / 2 = 11  r 0       0.75  * 2 = 1.5   -> 1
11 / 2 =  5  r 1       0.5   * 2 = 1.0   -> 1
 5 / 2 =  2  r 1
 2 / 2 =  1  r 0
 1 / 2 =  0  r 1

Read remainders upward: 101101   Read carries downward: .011
(45.375)10 = (101101.011)2

Binary to octal and hexadecimal

Because 8 = 2^3 and 16 = 2^4, you can group bits instead of dividing. Group three bits at a time for octal and four bits at a time for hex, starting from the radix point and padding with zeros at the ends. This is why engineers read registers in hex: each hex digit maps to exactly one nibble.

(101101.011)2
Octal : 101 101 . 011        = (55.3)8
Hex   : 0010 1101 . 0110     = (2D.6)16

Representing Negative Numbers

Hardware has no minus sign, so the most significant bit (MSB) is used to indicate the sign. Three schemes exist, and only one is used in practice for integer arithmetic.

SchemeHow -5 looks in 8 bitsRange for n bitsDrawback
Sign-magnitude1000 0101-(2^(n-1)-1) to +(2^(n-1)-1)Two zeros, separate add and subtract logic
1's complement1111 1010-(2^(n-1)-1) to +(2^(n-1)-1)Two zeros, end-around carry needed
2's complement1111 1011-2^(n-1) to +(2^(n-1)-1)None significant; single zero

To form the 2's complement of a number, invert every bit and add 1. A quicker hand method is to copy bits from the right up to and including the first 1, then invert the rest. For 8 bits the range is -128 to +127. The big advantage is that the same binary adder handles both signed and unsigned numbers; subtraction becomes addition of the 2's complement.

Worked Examples: Addition, Subtraction and Overflow

Example 1 computes 25 - 12 using 8-bit 2's complement. Example 2 shows what happens when the true result does not fit.

Example 1: 25 - 12
  +25  = 0001 1001
  +12  = 0000 1100  ->  -12 = 1111 0011 + 1 = 1111 0100

    0001 1001
  + 1111 0100
  -----------
  1 0000 1101   discard carry out -> 0000 1101 = +13  (correct)

Example 2: 100 + 50 in 8 bits
    0110 0100   (+100)
  + 0011 0010   (+50)
  -----------
    1001 0110   = -106 as signed  -> OVERFLOW
  Carry into MSB = 1, carry out of MSB = 0, they differ.

Overflow rule: in 2's complement addition, overflow occurs when two operands of the same sign produce a result of the opposite sign. In hardware this is detected as V = C(n) XOR C(n-1), the XOR of the carry into and out of the sign bit. Do not confuse this with the carry flag, which signals overflow only for unsigned numbers. Microcontrollers such as the ARM Cortex-M and AVR keep both a C flag and a V flag for exactly this reason.

Sign extension

When a signed value is widened, for example from 8 to 16 bits, copy the sign bit into all new upper bits. 1111 1011 (-5) becomes 1111 1111 1111 1011, still -5. Zero-filling instead would turn it into +251, a common bug when mixing signed and unsigned types in C or Verilog.

BCD and Other Codes

Binary Coded Decimal (8421 BCD) stores each decimal digit in its own 4-bit group, so 59 becomes 0101 1001. It wastes six of the sixteen codes but makes driving seven-segment displays and real-time clock chips such as the DS1307 straightforward, since those chips store time in BCD. When adding BCD digits, if a 4-bit sum exceeds 9 or produces a carry, add 6 (0110) to correct it.

BCD addition: 8 + 7
   1000
 + 0111
 -------
   1111   (15 > 9, invalid BCD)
 + 0110   (add 6)
 -------
 1 0101   -> carry 1, digit 5  = 15 in BCD (0001 0101)

Gray code is another code you will meet: successive values differ in only one bit, which avoids glitches in rotary encoders and is used to pass counter values between clock domains in FIFOs. Convert binary to Gray with G(i) = B(i+1) XOR B(i), keeping the MSB unchanged.

Common Mistakes

  • Grouping bits from the left for hex conversion of the integer part. Always group outward from the radix point.
  • Reading division remainders top to bottom. The first remainder is the least significant bit.
  • Using the carry flag to judge signed overflow. Use the XOR of the last two carries instead.
  • Forgetting that the 2's complement of -128 in 8 bits is -128 again, because +128 is out of range.
  • Treating BCD values from an RTC chip as plain binary, which shows 0x59 seconds as 89.

Summary

Binary, octal and hex are just different groupings of the same bits, and grouping is faster than division. 2's complement lets one adder handle both addition and subtraction, has a single zero and a range of -2^(n-1) to 2^(n-1)-1. Overflow is detected from the carries into and out of the sign bit, and BCD needs a +6 correction. Practise converting a few register values by hand, then move on to Boolean algebra, where these bits start flowing through logic.