For example, in binary 01+01=10 because the first digit overflows, and the extra "1" is carried to the next digit. Similarly, 1111+1=10000 because all the digits overflow in sequence. In general, adding a "1" will cause carries to ripple up through ones, flipping them to zeros, until it finally reaches a zero, which it will flip to a one.

Addition in hex is exactly the same--it's a bit tricker to add the larger digits involved, but carries work exactly the same. So 0x8+0x8=0x10, and 0xffff+0x1=0x10000.

Subtraction actually shows you how to represent negative numbers in binary. Consider -1==0-1: you just keep on flipping zeros to ones forever, "borrowing" against the future that never comes (just like the US banking system!). So -1 is represented (in principle) by an infinite number of ones, just like +1 is represented (in principle) by an infinite number of zeros followed by a one. In practice, we only store a finite number (usually 32 or 64) of bits, so on a 32-bit machine we define 32 ones as -1. The highest bit, then, can be thought of as a "sign bit"--negative numbers have that bit set, positive numbers have that bit clear. Suprisingly, it make sense to think of the sign bit in digit n as having value -2

Signed versus unsigned numbers are clearer if you draw them out for a 3-bit machine:

Bit Pattern |
Unsigned Value |
Signed Value |

000 |
0 |
0 |

001 |
1 |
1 |

010 |
2 |
2 |

011 |
3 |
3 |

100 |
4 |
-4 |

101 |
5 |
-3 |

110 |
6 |
-2 |

111 |
7 |
-1 |

Note that languages other than Java support "signed" as well as "unsigned" integer types explicitly. In C/C++/C#, typecasting to an unsigned value does nothing to the bits, and is hence a zero-clock operation. One way to speed up a "zero to n" bounds test on a signed value is to turn it into an unsigned value and just compare against n--that is, "if ((x>=0)&&(x<n)) ..." is the same as "if (((unsigned int)x)<n) ..." do exactly the same thing, because negative signed x's will turn into really huge unsigned x's!

In hex, -1 (in binary, all ones) is written in hex as 0xFFffFFff (on a 32-bit machine).

Another way to think about -1 is that it's like "99999" on a car's odometer--if you drive one more mile, you'll be at "00000", so you're really at mile -1!

The "obvious" way to represent negative numbers, just using the sign bit to store the +/- sign, is called one's complement, and has the weird behavior with zero plus the sign bit set--you get negative zero! For this reason, the approach above with a big negative sign bit, called two's complement, is the standard today.

void poke_at_int(int v) {

std::cout<<"For the int "<<v<<": ";

if (v&(1<<31)) std::cout<<"The sign bit is set (1).";

else std::cout<<"The sign bit is clear (0).";

std::cout<<"\n";

}

int foo() {

poke_at_int(0);

poke_at_int(+1);

poke_at_int(-1);

return 0;

}

This prints:

For the int 0: The sign bit is clear (0).

For the int 1: The sign bit is clear (0).

For the int -1: The sign bit is set (1).

Program complete. Return 0 (0x0)

You can also use bitwise OR to stick on new bits:

void poke_at_int(int v) {

std::cout<<"For the int "<<v<<": ";

v=v|(1<<2);

std::cout<<"Setting bit 2 makes the value "<<v;

std::cout<<"\n";

}

int foo() {

poke_at_int(0);

poke_at_int(+1);

poke_at_int(+2);

poke_at_int(+4);

poke_at_int(-1);

return 0;

}

This prints:

For the int 0: Setting bit 2 makes the value 4Note that 1<<2 is 4. Setting this bit on the value 4 (or 7, or 12, or...) does nothing, since that bit is already set. Setting this bit on -1 does nothing, since -1 has all its bits set already.

For the int 1: Setting bit 2 makes the value 5

For the int 2: Setting bit 2 makes the value 6

For the int 4: Setting bit 2 makes the value 4

For the int -1: Setting bit 2 makes the value -1

Program complete. Return 0 (0x0)

A good simple beginner entry:

int x, y; // input values to compare signsThis works using XOR (exclusive OR) on the sign bits of x and y. If these bits have different values, then XOR returns 1 (look at the truth table for XOR), so x^y is negative.

bool f = ((x ^ y) < 0); // true iff x and y have opposite signs

They get a lot more complicated from there!