Tuesday, May 21, 2013 0 comments

Learning the Java Language, Part 48: Nested Classes

So Java classes can have fields and methods both static and non-static, of varying levels of protection. You can also define classes within classes.

One of the main reasons to define a class inside of another class is encapsulation.Why, one might ask, would it be needed to define the class itself inside another as opposed to simply having an instance of the class as a field of the class? I would say if you wanted to keep the nested class code separate from the outer class code yet able to work with all of the internals of the outer class (the inner class code can access fields and methods of the outer class even if private, unless the inner class is static and the fields and methods of the outer class are not static, in which case you'd need an object reference to access it (because it wouldn't know which object's field or method to access otherwise).

Creating an inner class allows you to use separate code to do internal things to an outer class without adding to the outer class. Imagine the following:

public class MyClass{

  private int myInternalField;
  private HelperClass helper = new HelperClass(); //Defined externally

  public void someMethod(){
    //Code here to use helper to do something to myInternalField
  }

}

public class HelperClass{

  public void doSomethingWithMyInternalField(){
    //Won't work as-is
    //You'd have to add a getter and setter to MyClass
    //and probably make this method take a MyClass object
    //as a parameter like
    //helper.doSomethingWithMyInternalField( this )
    //^as called from someMethod in MyClass
  }



If you had private fields and wanted a helper class instance that was a field of your class to be able to work on your private fields, like your HelperClass object helper to be able to do something to myInternalField inside one of its own methods, the above wouldn't work as is, but the below would:

public class MyClass{

  
  private class HelperClass{

    public void doSomethingWithMyInternalField(){
      //Now you can freely access MyClass's myInternalField
    }

  } 

  private int myInternalField;
  private HelperClass helper = new HelperClass();

  public void someMethod(){
    helper.doSomethingWithMyInternalField();
  }

}

I made the class HelperClass above private so it can only be accessed inside MyClass. I made the method doSomethingWithMyInternalField() public so it could be accessed outside of HelperClass, in other words, from code within MyClass.

If you wanted your inner class to be public so classes outside of MyClass could have and use a HelperClass object you could do that, but every HelperClass object would have to be inside a MyClass object. In that case, imagining the above MyClass code as it is but with HelperClass being public instead of private, if you wanted to create a HelperClass object over in some other class,  you could do it like this:

public class SomeOtherClass{

  public void doSomethingElse(){
    MyClass outer = new MyClass();
    MyClass.HelperClass inner = outer.new HelperClass();
  }



Notice the syntax. You first create an instance of the outer class, MyClass. Then, the type of the inner class as you declare the reference inner is MyClass.HelperClass, and you assign the reference by typing the reference of your outer object followed immediately by the dot operator followed immediately by the new keyword followed by a space followed by the inner class constructor.

Next up: Inner Class Example
Friday, May 17, 2013 0 comments

Design Example: Four-Bit Full Adder

Previous: Design Example: One-Bit Half Adder

In this example we'll design a circuit that correctly carries out the binary addition of two four-bit binary numbers to compute a five-bit sum.

Design Overview
The objective is to take four-bit binary inputs \(x_3x_2x_1x_0\) and \(y_3y_2y_1y_0\) representing unsigned integers in binary, and produce a five-bit binary output \(z_4z_3z_2z_1z_0\) representing the sum of the inputs as an unsigned integer in binary.

In the ones place, \(x_0\) and \(y_0\) are added and we get the ones place sum \(z_0\) and the carry bit \(\text{c}_{\text{out}}\) for the next-higher place value, the twos place. Since this place value does not take any carry input, we can use the half adder designed in the previous post.

For the next three place values, the twos place, the fours place, and the eights place, we need adder circuits that can take three inputs instead of two, because we need to include the carry out bit from the next lower place value.

For the sixteens place of the output, we connect it directly to the carry out bit of the eights place full adder.

So here's a sketch of what the desired circuit looks like:
HA: Half Adder, FA: Full Adder
We came up with the design for the half adder circuit in the previous post. Now we need to come up with a design for a one-bit full adder that takes as input two input bits \(x_{\text{n}}\) and \(y_{\text{n}}\) and one input carry bit \(\text{c}_{\text{in}}\) and correctly outputs one sum bit \(z_{\text{n}}\) and one output carry bit \(\text{c}_{\text{out}}\). We can then insert this one-bit full adder with our half adder into the above schematic to complete our design.

Full Adder Arithmetic
Here's how a one-bit full adder should compute its sum and output carry bit for each of the eight combinations of input values:
Full Adder Arithmetic
Sum Circuit
If we look at the above image for a while, we can begin to see some patterns. Notice in the left column, where \(\text{c}_{\text{in}}\) is always \(0\), \(z_{\text{n}}\) is equal to \(x_{\text{n}}\, \text{XOR} \, y_{\text{n}}\), and in the right column, where \(\text{c}_{\text{in}}\) is always \(1\), \(z_{\text{n}}\) is equal to \(\overline{x_{\text{n}}\, \text{XOR} \, y_{\text{n}}}\). \(z_{\text{n}}\) is \(1\) whenever \(\text{c}_{\text{in}}\) and \(x_{\text{n}}\, \text{XOR} \, y_{\text{n}}\) are different and \(0\) when they are the same. So we can say that: \[z_{\text{n}} = \text{c}_{\text{in}} \, \text{XOR} \, (x_{\text{n}}\, \text{XOR} \, y_{\text{n}})\]The full adder sum circuit is then as shown below:
Full Adder Sum Circuit
Carry Circuit
To solve the carry circuit, let us put the information from the full adder arithmetic results into a truth table.
Carry Truth Table
 Taking a sum of products from the minterms of rows 3, 5, 6, and 7 (zero-indexed), we say: \[ \text{c}_{\text{out}} = \sum m(3, 5, 6, 7)\]which when the minterms are written becomes \[\overline{\text{c}_{\text{in}}} x_{\text{n}} y_{\text{n}} + \text{c}_{\text{in}} \overline{x_{\text{n}}} y_{\text{n}} + \text{c}_{\text{in}} x_{\text{n}} \overline{y_{\text{n}}} + \text{c}_{\text{in}} x_{\text{n}} y_{\text{n}}\]We can group the two outer terms together and the two inner terms together using the commutative and associative properties of the \(\text{OR}\) operation to rearrange the above into \[\overline{\text{c}_{\text{in}}} x_{\text{n}} y_{\text{n}} + \text{c}_{\text{in}} x_{\text{n}} y_{\text{n}} + \text{c}_{\text{in}} \overline{x_{\text{n}}} y_{\text{n}} + \text{c}_{\text{in}} x_{\text{n}} \overline{y_{\text{n}}}\] We can factor out \(x_{\text{n}} y_{\text{n}}\) of the first two terms using the distributive law to give \[ x_{\text{n}} y_{\text{n}}  (\overline{\text{c}_{\text{in}}}+ \text{c}_{\text{in}}) + \text{c}_{\text{in}} \overline{x_{\text{n}}} y_{\text{n}} + \text{c}_{\text{in}} x_{\text{n}} \overline{y_{\text{n}}}\]\((\overline{\text{c}_{\text{in}}}+ \text{c}_{\text{in}})\) is \(1\) by the complement law, and anything \(\text{AND}\)ed with \(1\) is that thing by the identity law, so the first term becomes \(x_{\text{n}} y_{\text{n}}\), making the equation \[x_{\text{n}} y_{\text{n}}   + \text{c}_{\text{in}} \overline{x_{\text{n}}} y_{\text{n}} + \text{c}_{\text{in}} x_{\text{n}} \overline{y_{\text{n}}}\] We can factor out \(\text{c}_{\text{in}}\) of the second and third terms using the distributive law, giving \[x_{\text{n}} y_{\text{n}}   + \text{c}_{\text{in}} (\overline{x_{\text{n}}} y_{\text{n}} + x_{\text{n}} \overline{y_{\text{n}}})\]And \(\overline{x_{\text{n}}} y_{\text{n}} + x_{\text{n}} \overline{y_{\text{n}}}\) is the definition of \(x_{\text{n}} \, \text{XOR} \, y_{\text{n}}\), frequently written as \(x_{\text{n}} \oplus y_{\text{n}}\), making our equation \[x_{\text{n}} y_{\text{n}}   + \text{c}_{\text{in}} (x_{\text{n}} \oplus y_{\text{n}})\]The full adder carry out bit circuit is then shown as below:
Full Adder Carry Circuit
Complete Circuit
Notice how both the sum circuit and carry circuit have an \(\text{XOR}\) gate with \(x_{\text{n}}\) and \(y_{\text{n}}\) as input. We can use a single \(\text{XOR}\) gate in the complete circuit to save a gate as shown below in the circuit for a one-bit full adder:
One-Bit Full Adder
And here is an image of the complete circuit with half adder substituted in the least-significant bit (LSB) position and full adders substituted in the higher bit positions:
Four-Bit Full Adder
Next: Design Example: Multiplexer
Wednesday, May 15, 2013 0 comments

Learning the Java Language, Part 47: Q&E: Objects

Questions and Exercises. Here are my answers and solutions to their questions and exercises.

Questions
  1. What's wrong with the following program?
    public class SomethingIsWrong {
      public static void main(String[] args) {
        Rectangle myRect;
        myRect.width = 40;
        myRect.height = 50;
        System.out.println("myRect's area is " + myRect.area());
      }
    }
    A Rectangle object was never created with a the new keyword and a constructor call, only a reference to one was declared. The reference myRect currently refers to no object.
  2. The following code creates one array and one string object. How many references to those objects exist after the code executes? Is either object eligible for garbage collection?
    ...
    String[] students = new String[10];
    String studentName = "Peter Parker";
    students[0] = studentName;
    studentName = null;
    ...
    After this code executes, one reference to the array with string object "Peter Parker" at index 0 exists. (students[0] still refers to the "Peter Parker" object, even if studentName does not.) Since the "Peter Parker" string object is referred to by index 0 of the array object, and the array object is referred to by the students reference, neither object is eligible for garbage collection. (note: If you added the line students[0] = null; to the end of the snippet above, then the "Peter Parker" string object would have no references to it and be eligible for garbage collection.
  3. How does a program destroy an object that it creates?
    When an object has zero references to it (setting all of the program's references to the object equal to null), the Java garbage collector frees the memory used by the object, effectively destroying it. It is the Java virtual machine that actually does this, not the user's program.
Exercises 
  1. Fix the program called SomethingIsWrong shown in Question 1.
    public class SomethingIsWrong {
      public static void main(String[] args) {
        Rectangle myRect = new Rectangle();
        myRect.width = 40;
        myRect.height = 50;
        System.out.println("myRect's area is " + myRect.area());
      }
    }
  2. Given the following class, called NumberHolder, write some code that creates an instance of the class, initializes its two member variables, and then displays the value of each member variable.
    public class NumberHolder {
      public int anInt;
      public float aFloat;
    }
    My answer:
    NumberHolder myNumberHolder = new NumberHolder();
    myNumberHolder.anInt = 3;
    myNumberHolder.aFloat = 2.6;

    System.out.println("myNumberHolder.anInt = " + myNumberHolder.anInt);
    System.out.println("myNumberHolder.anFloat = " + myNumberHolder.aFloat);
Next up: Nested Classes
Tuesday, May 14, 2013 0 comments

Design Example: One-Bit Half Adder

Previous: Sums of Products and Products of Sums

In this example we'll design a circuit that correctly carries out the binary addition of two inputs and produces a sum value and a carry value.

Binary arithmetic
With two input values that can each take exactly one of two values, the sum for a given place value has four possible values. They are shown below.
Value of Sum Output
The value of the carry bit output is shown in blue alongside the sum output for the same four input scenarios in the image below.
Value of Carry Output
Shown below is a truth table with the two inputs labeled \(x_1\) and \(x_0\), the sum output labeled \(\text{s}\), and the carry output labeled \(\text{c}\):
Truth Table for Half Adder
Sum Circuit
To find a circuit solution for \(\text{s}\), we can use either minterms or maxterms. I'll use minterms. The first and second rows (indexed from zero) have \(1\) in the output for \(\text{s}\). So we have: \[ \text{s} = \sum m(1, 2)\]expanding this into a sum of products, we get \[ \text{s} = \overline{x_1}x_0 + x_1 \overline{x_0}\]The logic circuit that implements this function looks like this:
Sum Circuit
This logic function, whose output value is \(1\) when exactly one of its two input values is \(1\) and whose output is \(0\) otherwise, is so common that it has its own symbol as a single logic gate called an exclusive-\(\text{OR}\), or \(\text{XOR}\) gate. So the following circuit is the equivalent of the above circuit using the \(\text{XOR}\) gate:
XOR Circuit
Carry Circuit
We can tell by looking at the truth table above that the function for the carry output is a simple \(\text{AND}\) gate.

Complete Circuit
The complete circuit with two inputs and two outputs is shown below:
Next: Design Example: Four-Bit Full Adder
Monday, May 13, 2013 0 comments

Learning the Java Language, Part 46: Q&E: Classes

Questions and Exercises. Here are my answers and solutions to their questions and exercises.

Questions
  1. Consider the following class:
    public class IdentifyMyParts {
    public static int x = 7;
    public int y = 3;
    }


    a. What are the class variables?
    x
    b. What are the instance variables?
    y
    c. What is the output from the following code:
    IdentifyMyParts a = new IdentifyMyParts();
    IdentifyMyParts b = new IdentifyMyParts();
    a.y = 5;
    b.y = 6;
    a.x = 1;
    b.x = 2;
    System.out.println("a.y = " + a.y);
    System.out.println("b.y = " + b.y);
    System.out.println("a.x = " + a.x);
    System.out.println("b.x = " + b.x);
    System.out.println("IdentifyMyParts.x = " + IdentifyMyParts.x);

    The following is the output at the command prompt:
    a.y = 5
    b.y = 6
    a.x = 2
    b.x = 2
    IdentifyMyParts.x = 2
Exercises
  1. Write a class whose instances represent a single playing card from a deck of cards. Playing cards have two distinguishing properties: rank and suit. Be sure to keep your solution as you will be asked to rewrite it in Enum Types.
    Here is my PlayingCard class.
  2. Write a class whose instances represent a full deck of cards. You should also keep this solution.
    Here is my Deck class.
  3. Write a small program to test your deck and card classes. The program can be as simple as creating a deck of cards and displaying its cards.
    Here is my DeckTest class.
Next up: Questions and Exercises: Objects
Friday, May 10, 2013 0 comments

Sums of Products and Products of Sums

Previous: Synthesis with AND, OR, and NOT Gates

In the previous post, I mentioned the technique of looking at all the rows in a truth table for which the output was \(1\), \(\text{AND}\)ing all the terms in such a row together, and then \(\text{OR}\)ing all those row products together. This is known as a Sum of Products. There's also such a thing as a Product of Sums. I'll talk about both in this post.

Minterms
A minterm is just a name for a specific kind of boolean algebra function. Given a set of \(n\) input variables, if a boolean algebra function includes every one of those \(n\) inputs exactly once, and if the operation done is to \(\text{AND}\) the terms together, in complemented or uncomplemented form, then the function is a minterm.

Say you have three input variables in all and call them \(x_0\), \(x_1\), and \(x_2\).
  • \(x_2 x_1\) is not a minterm because it does not include \(x_0\)
  •  \(x_2 (\overline{x_1} + x_0)\) is not a minterm because it is not only complemented or uncomplemented terms \(\text{AND}\)ed together
  • \(x_2 \overline{x_2} x_1 x_0\) is not a minterm because it does not include each complemented or uncomplemented term once and only once
  • \(\overline{x_2} x_1 \overline{x_0}\) is one of the eight minterms possible with three input variables
Now as long as you line up your input variables consistently, you can identify a particular permutation of all the possible minterms by a single number. Then for a set of \(n\) input variables, there are \(n\) minterms. If you consider every complemented variable is if it were a binary \(0\) and every uncomplemented variable as if it were a binary \(1\), since we are consistently ordering the input variables, and since as a condition of being a minterm, every input variable appears once and only once, a minterm can be interpreted as a binary number. One convention is to use a lower-case \(m\) subscripted with a number to represent a minterm. For example, given an input set of four input variables \(x_3\), \(x_2\), \(x_1\), and \(x_0\), there are \(2^{4}\), or \(16\) minterms. The compact \[m_{13}\] represents \[x_{3} x_{2} \overline{x_1} x_{0}\] because viewing uncomplemented variables as \(1\)s and complemented variables as \(0\)s, this is the decimal number \(13\) in binary (\(13_{10} = 1101_{2}\)). Of course the actual values of the variables can make the value of the group, if viewed as a binary number, something different. Writing \(m_{13}\) instead of \(x_{3} x_{2} \overline{x_1} x_{0}\) begins to save a lot of writing after dealing with minterms for a while, though. To reiterate, a value in this notation, such as \(m_{10}\), represents a minterm, and says nothing of what the values of input variables are at any time. (Note that it doesn't tell you how many input variables there are either. That you have to know.)

Once you have all the minterms for rows in a truth table for which the output is \(1\), you can sum the products by \(\text{OR}\)ing them all together. Say we have a function \(f\) with three inputs, so there are \(2^3 = 8\) minterms  we label \(m_0\) - \(m_7\). Say the output is \(1\) for rows \(0\), \(2\), \(3\), \(4\), and \(7\). A widely-used notation instead of writing the \(+\) operator between each pair of minterms is to use the \(\sum\) symbol. For this example, we might write something like this: \[\sum (m_0, m_2, m_3, m_4, m_7)\]Even more stripped down is the also-seen notation for sums of products \[\sum m(0, 2, 3, 4, 7)\]This is much faster and cleaner than writing \[\overline{x_2}\, \overline{x_1}\, \overline{x_0} + \overline{x_2}x_1 \, \overline{x_0} + \overline{x_2}x_1x_0 + x_2\overline{x_1}\, \overline{x_0} + x_2x_1x_0\]
Maxterms
DeMorgan's laws can be used to show that, for instance, a minterm such as \(x_n x_{n-1} \cdot \cdot \cdot x_2 x_1 x_0\) is logically equivalent to \(\overline{\overline{x_n} + \overline{x_{n-1}} + ... + \overline{x_2} + \overline{x_1} + \overline{x_0}}\) . This would describe the \(2^n\)th row which has a \(1\) as its output (remember the convention for minterms where uncomplemented variables are \(1\)s for ordering purposes).

Now if instead we wanted to focus on rows which had a \(0\) as the function's output, the dual form would look like  \(\overline{x_n} + \overline{x_{n-1}} + ... + \overline{x_2} + \overline{x_1} + \overline{x_0}\). Just to be clear, we're no longer drawing an equivalent form of minterms, since now we're finding the rows with output \(0\). One final thing we can do to simplify our representation is to say that when finding maxterms, our convention will be opposite to that of our minterm ordering convention: with maxterms, we let complemented terms be symbolized as \(1\)s and uncomplemented terms be symbolized as \(0\)s.

So to use the three-element example, the zeroth maxterm which corresponds to all three elements having the value \(0\) would be, using the variables, \[x_2 + x_1 + x_0\] and the notation commonly used to write down maxterms is the capital \(M\) with subscript to identify which maxterm we are referring to. So the above using this notation would be \[M_0\] With minterms, you find the desired logic function by \(\text{OR}\)ing minterms, making a sum of products out of the rows for which the truth table has \(1\)s, but with maxterms, you find the desired logic function by \(\text{AND}\)ing maxterms, making a product of sums out of the rows for which the truth table has \(0\)s.

After all of this, if, say, rows \(1, 5,\) and \(6\) have \(0\)s, the product of sums would be \[M_1 \cdot M_5 \cdot M_6\]A widely-used notation instead of writing the \(\cdot \) operator between each pair of maxterms is to use the \(\prod \) symbol. For this example, we might write something like this:\[ \prod (M_1, M_5, M_6)\]Even more stripped down is the also-seen notation for products of sums \[ \prod M(1, 5, 6) \]This is much faster and cleaner than writing \[(x_2 + x_1 + \overline{x_0}) \cdot (\overline{x_2} + x_1 + \overline{x_0}) \cdot (\overline{x_2} + \overline{x_1} + x_0)\]Notice how the minterm example given above is for when rows \(0, 2, 3, 4\) and \(7\) are \(1\), and the maxterm example given above is for when rows \(1, 5\) and \(6\) are \(0\), so these sum of products and product of sums are equivalent.

Next: Design Example: One-Bit Half Adder
 
;