Lecture 18: Boolean Logic


Finishing Up Applets

In the previous lecture I introduced how to draw simple objects inside of an Applet window. Now I'll demo an example that also uses listeners: a way to respond to actions from the users. This example just responds to actions that the user makes with the mouse. There's also a Timer object that I'll use as a quick way to animate my graphics. Here's the example code here .

Reviewing Binary Numbers

In previous lectures we introduced the idea of representing numbers in binary notation. This means using a 2-digit number system (using 0's and 1's) instead of our usual 10 digit number system (using 0, 1, 2, 3, 4, 5, 6, 7, 8, and 9) or decimal number system. In your usual decimal system you're dealing with powers of 10. So, the number 125 is really 1*102 + 2*101 + 5*100. So, any other digit added onto the front of the number is just multiplied against the next power of 10.

The same is true of the binary number system, except now we're dealing with powers of 2. So, the number 1011 in powers of 2 is: 1*23 + 0*22 + 1*21 + 1*20. In decimal digits, this becomes: 1*8 + 0*4 + 1*2 + 1*1 = 11. Make note of the difference between writing 11 in decimal notation (eleven) and in binary notation (three). Why do we use powers of our base value? Well, take 101 for example. That's larger than any of our 10 decimal digits, 0-9. Similarly, taking 1*102 = 10*101, we get 10*101 - 9*101 = 1*101 > 9. So, 1*102 is larger than any possible combination of the smaller powers of 10 (using only 0-9 as possible multiples). Similarly, we get the same effect with using powers of 2 and the binary number system. In this way we cover all possible values exactly once.

But why binary numbers? Theoretically, there's no reason to prefer binary numbers over decimal numbers, hexadecimal numbers (base-16) or any other base system. Practically, though, binary numbers are more reliable. It's easier to represent only two values rather than multiple values. On vs. Off, High vs. Low, Left vs. Right, Positive vs. Negative, Clockwise vs. Counterclockwise. By having only two possible values it's easier to keep those values separated so there's no confusion. In the case of computers, things have typically been represented with magnetic field directions or with electrical circuits. For electric circuits, we might have a low voltage, like 0, represent 0 and a high voltage, say +45, represent 1. If for some reason our high voltage decays a little bit then its intended level, then maybe we can still consider it as a "1" because it hasn't gotten anywhere close to the level where we would consider it a "0". If we were using a decimal number system instead, it would be much easier to accidentally read an 8 as a 7 or a 9 if our voltage is slightly off. A binary system gives us the greatest separtion between values and so the greatest chance for reliability. To help you get used to understanding powers of 2 (the basis for binary numbers) some notable powers are given below.

Term # of bytes Level
Kilobyte (KB) 1024 or 210 bytes Thousands of bytes
Megabyte (MB) 10242 or 220 bytes Millions of bytes
Gigabyte (GB) 10243 or 230 bytes Billions of bytes
Terabyte (TB) 10244 or 240 bytes Trillions of bytes
Binary #Decimal #
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
1000 8
1001 9
1010 10

Transistors in Computers

In very old computers, say from 1955 to 1975, magnetic cores were used to represent comptuer memories. This allowed 0's and 1's to be represented by the direction of the magnetic field on the core (clockwise vs. counterclockwise). The problem with this is that the metal "doughnut" needed to make these cores was about 1/50th of an inch in its inner diameter. This is usually considered small, but not when you're needing to represent million of 0's and 1's. Today the elementary block for computers is the transistor. This was a device first invented around 1951 by Dr. William Shockley, John Bardeen and Walter Brattain. It is a switch that can be electrically turned ON or OFF. If the transistor is ON then it will allow electricity to pass through it. If the transistor is OFF then it will not allow electricity to pass. A diagram of a transistor is given below.

This gives a switch that is much smaller (current technology fits at least 10 million transistors in 1 square centimeter of space) and much faster. The old magnetic cores needed to have mechanical parts while this electrically controlled switch is much faster. By using these transistors we can have a current represent ON or a binary value of 1, and no current represent OFF or a binary value of 0. Transistors are constructed from materials called semiconductors such as silicon. Large numbers of transistors and the electrical paths connecting them may be imprinted on wafers of semiconductors using a photographic process. The resulting device is known either as an integrated circuit or as a chip.

Different chips are created for the memory, processor, or other parts of the computer, and they are placed on a circuit board to connect them. By using a photographic process, we can take advantage of the fact that light can be focused to cut tiny designs with great precision and accuracy. It also allows for a single template or mask to be made for describing a single circuit. This mask may then be used to create many copies of a circuit just as a photographic negative could be used to make many prints (remember, before digital cameras?).

Boolean Logic

Once we have an atomic unit like a transistor, we can start making boolean decisions. This is something you were already doing in your Java programs. Now we're going to try it at a more primitive level. Remember the 3 basic boolean operators that we worked with n Java: logical AND, OR, and NOT. This idea of mathematical logic was devised by the English mathematician George Boole (1815 - 1864). Like so many other discoveries, at the time he published his work its importance was not recognized. Now it is the basis for the internal logic of computers.

First, let's try constructing a logical AND statement using transistors. For the value true we'll use the value 1 and for false we'll use the value 0. (Remember, 0's and 1's represented by whether an electrical current or a voltage is present or not is all that computers have to work with.) Here's logical AND:

The actual current that could be given as output comes from the source marked "Power". The two inputs that we perform the logical AND operation on serve as the control inputs to the two transistors (the circles). If an input has a signal of 1, it closes the transistor and allows power to flow. A signal of 0 leaves the transistor open. Thus, for the current to flow out, and give an output of 1, we require both input 1 and input 2 to have value 1. The opposite is the case for the logical OR operation:

Finally, for logical NOT we actually need to introduce an electrical part called a resistor. This causes the current to avoid taking this path if there is an easier path to take. You can think of an open transistor, one that does not allow current to pass through, as a resistor with infinite resistance. Here's the logical NOT:

Now that we've got these logical operators, we can make abstraction to help us represent them. The common symbols for each of logical AND, OR, and NOT are given below.

Truth Tables and Notation

What if we want to make more complicated decisions? First, we have to know exactly what result we want for every possible input. This can be represented using a truth table. Note that for 2 inputs, there will only be 4 possible combinations. For 3 inputs, 8 possible, and in general, for n inputs there will be 2^n possible combinations. Here's an example truth table.

Input 1Input 2Input 3Output
0 0 0 0
0 0 1 1
0 1 0 1
0 1 1 0
1 0 0 1
1 0 1 0
1 1 0 0
1 1 1 0

Given this truth table, we can then construct logical gates that represent it. While the circuit diagrams previously mentioned could be useful if we were actually designing circuits, for simply stating combinations of logical operators we can use shorter notation. For logical AND, we can say (A * B) in place of "A AND B". In place of logical OR, we can say (A + B) in place of "A OR B". For logical NOT, we can still use !(A) or, for a more compact notation, we can use a bar above the expression we wish to negate: A. We can also use this bar over larger expressions: (A + B).