Binary (and other base) numbers

1 Unsigned place value numbers

Unsigned place value numbers require two idea:

We’ll draw these like so:

1.1 Meaning

The numeric meaning of an unsigned base-bb number xx is the sum of xibix_i b^i for all indices ii.

3 4 0 (base ten) = 0100+4101+3102=3400 \cdot 10^0 + 4 \cdot 10^1 + 3 \cdot 10^2 = 340

1 5 4 (base sixteen) = 4160+5161+1162=3404 \cdot 16^0 + 5 \cdot 16^1 + 1 \cdot 16^2 = 340

1 0 1 0 1 0 1 0 0 (base two) = 020+021+122+023+124+025+126+027+128=3400 \cdot 2^0 + 0 \cdot 2^1 + 1 \cdot 2^2 + 0 \cdot 2^3 + 1 \cdot 2^4 + 0 \cdot 2^5 + 1 \cdot 2^6 + 0 \cdot 2^7 + 1 \cdot 2^8 = 340

What is 3 4 0 (base eight) ? 224
What is 3 4 0 (base five) ? 95
What is A C E (base sixteen) ? 2766
What is A C E (base thirty-six) ? 13406

1.2 Finding the value in a given base

Finding a value in a given base cane be done by repeated division with remainder.

  1. Find the smallest bib^i that is larger than xx. You’ll need ii places.
  2. For kk from i1i-1 to 00, inclusive of both endpoints:
    1. Divide xx by bkb^k, keeping the whole number quotient and remainder
    2. Put the quotient in place kk
    3. Replace kk with the remainder for the next iteration of this loop

To convert 340 to base 3,

  1. 36=7293^6 = 729, the smallest power of 33 which is greater than 340340. Thus we’ll have 6 places:

    (base three)

  2. Repeat for kk from 5 to 0, inclusive of both endpoints:

    k=5k=5

    340÷35=1 remainder 97340 \div 3^5 = 1 \text{ remainder } 97

    1 (base three)

    k=4k=4

    97÷34=1 remainder 1697 \div 3^4 = 1 \text{ remainder } 16

    1 1 (base three)

    k=3k=3

    16÷33=0 remainder 1616 \div 3^3 = 0 \text{ remainder } 16

    1 1 0 (base three)

    k=2k=2

    16÷32=1 remainder 716 \div 3^2 = 1 \text{ remainder } 7

    1 1 0 1 (base three)

    k=1k=1

    7÷31=2 remainder 17 \div 3^1 = 2 \text{ remainder } 1

    1 1 0 1 2 (base three)

    k=0k=0

    1÷30=1 remainder 01 \div 3^0 = 1 \text{ remainder } 0

    1 1 0 1 2 1 (base three)

Thus 340340 is 110121 in base-3.

1.3 Bases that are powers of other bases

If b=βnb = \beta^n then each base-bb digit maps to exactly nn base-β\beta digits.

Because 16=2416 = 2^4, each digit of a base-16 number maps directly to 4 digits of a base-2 number.

A C E (base sixteen) 1 0 1 0 1 1 0 0 1 1 1 0 (base two)

We use this feature extensively in computing. Processors typically operate in base-2 (binary), but we find base-2 hard to read (too many 0s and 1s and we get lost) so we write base-8 (octal: 23=82^3=8) or base-16 (hexadecimal: 24=16)2^4 = 16) instead. Memory, files, and network communication is typically defined in base-256 (bytes) but we find base-256 hard to read (we only have 36 digits) so we write each byte in base-16 (162=25616^2 = 256) using two characters for one digit.

This document is stored on a file and transmitted over a network in a byte-oriented format called HTML. The first eight bytes are 3C 21 44 4F 43 54 59 50.

I started writing this example 1705682415 seconds after the POSIX epoch. In base-256 that is 65 AA A5 EF (base two hundred fifty-six)

2 Addition

To add two numbers represented in the same base,

  1. Initialize a carry digit to 0
  2. Work from index i=0i=0 up; for each index ii,
  1. Add the digits at index ii and the carry digit
  2. Replace the carry digit with index 1 of the sum
  3. Use index 0 of the sum as index ii of the result
  1. When we run out of digits in a number, use 0s
  2. Stop once all digits in both numbers are used up and the carry is 0

It is common to draw this entire process by putting the two numbers to add one atop the other, the carry digits above them both, and the result below them both.

To add base-10 numbers 340 and 173 we

  1. add carry 0 and digits 0 and 3 to get result 3 and carry 0
  2. add carry 0 and digits 4 and 7 to get result 1 and carry 1
  3. add carry 1 and digits 3 and 1 to get result 5 and carry 0

We’d draw this like so:

3 4 0 1 7 3 + 5 1 3 0 1 0

To add base-2 numbers 100111 and 1011 we

  1. add carry 0 and digits 1 and 1 to get result 0 and carry 1 (0+1+1=20+1+1=2 which is 10 in base-2)
  2. add carry 1 and digits 1 and 1 to get result 1 and carry 1 (1+1+1=31+1+1=3 which is 11 in base-2)
  3. add carry 1 and digits 1 and 0 to get result 0 and carry 1
  4. add carry 1 and digits 0 and 1 to get result 0 and carry 1
  5. add carry 1 and digits 0 and 0 to get result 1 and carry 0
  6. add carry 0 and digits 0 and 0 to get result 0 and carry 0
  7. add carry 0 and digits 1 and 0 to get result 1 and carry 0

We’d draw this like so:

1 0 0 0 1 1 1 1 0 1 1 + 1 0 1 0 0 1 0 0 0 1 1 1 1 0

3 Subtraction

There are several models of subtraction taught in schools, but the one that works best on computers is generally not one of them.

Define b’s complement of a digit dd to be b1db-1-d. When working in base b we always use b’s complements and just call them the complement of the digit.

Complements in two example bases are shown below

Digit two’s complement ten’s complement
0 1 9
1 0 8
2 7
3 6
4 5
5 4
6 3
7 2
8 1
9 0

With this definition, we can subtract xyx-y by adding xx and the digit-by-digit complement of yy (including complimenting the extra-digit 0s) using an initial carry of 11 instead of 00. We stop once we’ve used up all digits and the carry is 1.

To subtract base-10 numbers 340 and 124 we

  1. compliment 0…0124 as 9…9875
  2. add 0…0340 + 9…9875 + 1 in the usual way, stopping when the digits are used and the carry is 1
3 4 0 8 7 5 + 2 1 6 1 0 1

If we’d not stop we still would get the same answer:

... 0 0 0 3 4 0 ... 9 9 9 8 7 5 + ... 0 0 0 2 1 6 ... 1 1 1 1 0 1

4 Signed place-value numbers, computer style

Signed place-value numbers in computers use a finite number of digits. They do addition and subtraction the same way they do for unsigned numbers, but they discard high-order digits that they can’t store.

In this model, x-x is 0x0-x and is the complement of the digits of xx, plus 1.

The 6-digit base-10 value of −340 is 999659 + 1 = 999660.

The 8-digit base-2 value of −101101 is 11010010 + 1 = 11010011.

When using signed numbers like this, we also need to distinguish between positive and negative numbers. For addition, subtraction, and multiplication it doesn’t matter if a number if positive or negative, but for comparisons and some division algorithms it does. The most common approach is to make half of all numbers negative, meaning in particular that a number is negative if the highest-order digit is b2b \over 2 or larger.

For base-2 (binary) numbers, the most common in computing, this means a signed integer is negative if the highest-order bit is 1, and is non-negative if that bit is 0.

In C and C++, the signed char and unsigned char types are 8-digit base-2 numbers.1 Annoyingly, char might be shorthand for signed char on one machine and unsigned char on another. If you are using char as a number type, always include an explicit signedness indicator.

Let’s consider a few numbers’ base-2 representation:

base 10 8-digit base 2
124 1 1 1 1 1 0 0
225 1 1 1 0 0 0 0 1
340 0 1 0 1 0 1 0 0 1

To make these into 8-digit numbers, empty boxes will be receive the digit 0 and digits that don’t have a box will be discarded. Thus, the following code stores the values indicated in the comments

  signed char s124 = 124; // +124
unsigned char u124 = 124; // +124
  signed char s225 = 225; //  -31
unsigned char u225 = 225; // +225
  signed char s340 = 340; //  +84
unsigned char u340 = 340; //  +84