Tuesday July 11, 2000


Quiz 19


1. If the value of counter is 1, then what is the value of ++counter?

2. What is the syntax of a for loop?

3. What are the four primary components in the signature of a method?

4. True/False Any for loop can be rewritten as a while loop.




































Announcement

The School of CIS will be having a cookout on Thursday in the courtyard and everyone is invited to attend.

Programming Assignment 2

This short assignment is designed to give you experience with the concepts of class and instance variables, class and instance methods, and constructors, and how they work together.

Evariste decides that in order to gain more understanding of Object Oriented Programming he is going to write a small class called Binary. He will have five instance variables in his class.

original of type String
quadra of type String
octal of type String
hexadecimal of type String
decimal of type int

He will have four instance methods in his class.

toQuadra accepts no parameters and returns type String
toOctal accepts no parameters and returns type String
toDecimal accepts no parameters and returns type int
toHexadecimal accepts no parameters and returns type String
toString returns the String equivalent of this class (we will discuss this topic Tuesday and Wednesday)


He will have one class method called equiv that is overloaded.

The method will accept two, three or four parameters. It will return type String.

The constructor for Evariste's class will accept one parameter of type String.

The purpose of Evariste's class is to accept a binary number written as a string. Each of the instance methods will be used to convert that binary number into the appropriate number system. When the constructor is called, its job will be to give a value to original, and then call each of the four conversion instance methods to give values to the instance variables, quadra, octal, decimal, and hexadecimal.

The method equiv will be used to accept two, three, or four bits (characters) and convert that group of bits to the appropriate equivalent. For example, if the bits we send to one implementation of the method are ``1'',``1'', and ``1'', the method would recognize that since we are sending it three bits, we want the octal equivalent, so it would return the String ``7''.

The method toString will be used to prepare a formatted result. The output this method will produce will be

Binary QuadraDecimal Octal Decimal Hexadecimal
1010 22 12 10 A


Evariste has created a new number system called the quadradecimal number system which has only the digits 0, 1, 2, and 3.

He has decided that the easiest way in which to convert a binary number to other systems is to use the methods available in the String class.

He decides the easiest way to proceed with converting a binary number to a quadradecimal is with the following algorithm. Assume that there is a binary number stored in the String original.
1. Let l = the length of the string original.

2. Let n = the integer part of the quotient l/2. 
(He decides on this because like the conversion
from binary to octal and hexadecimal he must
take groups of bits. Since the base of the
quadradecimal system, 4, is 22, he must take
groups of two binary digits and convert them to
their quadradecimal equivalent).

He knows now that there are n groups of 2 bits
in original. Now he must determine is there are
any bits left over.

3. Let r = the remainder in the division l/2.

If r is 0 he knows that there are exactly n
groups of 2 bits in original and no more. If r
is 1 he knows that there are n groups of 2 bits
in original and 1 left over. If there is one left
over he must accomodate for this.

4. if (r == 1)
      get quadradecimal equivalent of ``0" and
the first character in original and store the
equivalent in an output string.

Now that he has accounted for the first character
if there is one left over, he can now go through
the rest of the string taking groups of two bits
and converting them to their quadradecimal equivalent.

If r was 1, then he will start breaking up the
 string into groups of 2 beginning with position 1.
If r was 0, then he will start breaking up the
 string into groups of 2 beginning with position 0.

5. for (initialize counter to r; as long as counter
is less than length of original; increment counter by 2) { 
      Get quadradecimal equivalent of two characters of original beginning
      at position counter.
      concatenate the equivalent into the output string.
   }

6. Return the output string.
Evariste decides he can carry out the conversion from binary to octal and hexadecimal in the same way.

He decides the conversion from binary to decimal is even easier.

Your task is to write the class Binary and have it carry out the proposed tasks. The class you write should contain a main method in which you instantiate the class, and make a call to its toString method to produce the formatted output.

A Solution

public class Binary {

// We now declare our instance variables.

   String original;
   String quadra;
   String octal;
   int decimal;
   String hexadecimal;

   public Binary(String original) {

// The purpose of the constructor is to initialize the instance variable
// original and initialize the other instance variables by making calls
// to the corresponding instance method.

      this.original = original;
      quadra = toQuadra();
      octal = toOctal();
      decimal = toDecimal();
      hexadecimal = toHexadecimal();
   }

   public String toQuadra() {

// We follow the strategy discussed in class. We determine whether
// or not the length of the string is evenly divisible by 2.

      String outputString = "";
      String temp = "";
      int r = original.length() % 2;

// If it is not, then we take the first bit and get its quadradecimal
// equivalent and initialize our outputString. Otherwise we initialize
// our output string to an empty string.
  
      if (r == 1)
         outputString = Binary.equiv("0",original.substring(0,1));
      else
         outputString = "";

// We now step through the rest of the string grabbing groups of 2 bits,
// converting them to their quadradecimal equivalent, and then
// concatenating that equivalent to the outputString.

      for (int counter = r;counter < original.length();counter+=2) {
         String bit1 = original.substring(counter,counter+1);
         String bit2 = original.substring(counter+1,counter+2);
         outputString = outputString.concat(Binary.equiv(bit1,bit2));
      }

      return(outputString);
   }
         
   public String toOctal() {

// We follow almost the same strategy as in toQuadra(). We determine
// whether or not the length of the string is evenly divisible by 3.

      String outputString = "";
      String temp = "";
      int r = original.length() % 3;

// If it is not, then either it has remainders 2 or 1 when divided by 3.
// If it has remainder 2, then we left pad the string with a 0 and
// get the octal equivalent of the first three bits. If it has remainder
// 1, then we left pad the string with 00 and get the octal equivalent of
// the first three bits. We initialize the outputString to the equivalent.
// If it is evenly divisible by 3, then we initialize the outputString to
// an empty string.
  
      if (r == 2)
         outputString = Binary.equiv("0",original.substring(0,1),original.substring(1,2));
      else if (r == 1)
         outputString = Binary.equiv("0","0",original.substring(0,1));
      else
         outputString = "";

// We now step through the string grabbing groups of 3 bits and converting
// them to their octal equivalent and concatenating the equivalent to 
// the outputString.

      for (int counter = r;counter < original.length();counter+=3) {
         String bit1 = original.substring(counter,counter+1);
         String bit2 = original.substring(counter+1,counter+2);
         String bit3 = original.substring(counter+2,counter+3);
         outputString = outputString.concat(Binary.equiv(bit1,bit2,bit3));
      }

      return(outputString);
   }

         
   public String toHexadecimal() {

// We follow almost the same strategy as in toQuadra() and toOctal(). We
// determine whether or not the length of the string is evenly divisible
// by 4.

      String outputString = "";
      String temp = "";
      int r = original.length() % 4;

// Depending on the remainder we initialize the outputString.
 
      if (r == 3)
         outputString = Binary.equiv("0",original.substring(0,1),original.substring(1,2),original.substring(2,3));
      else if (r == 2)
         outputString = Binary.equiv("0","0",original.substring(0,1),original.substring(1,2));
      else if (r == 1)
         outputString = Binary.equiv("0","0","0",original.substring(0,1));
      else
         outputString = "";

// We now step through the string grabbing groups of 4 bits and converting
// them to their hexadecimal equivalent and concatenating that equivalent
// to the outputString.

      for (int counter = r;counter < original.length();counter+=4) {
         String bit1 = original.substring(counter,counter+1);
         String bit2 = original.substring(counter+1,counter+2);
         String bit3 = original.substring(counter+2,counter+3);
         String bit4 = original.substring(counter+3,counter+4);
         outputString = outputString.concat(Binary.equiv(bit1,bit2,bit3,bit4));
      }

      return(outputString);
   }

   public int toDecimal() {

// We step through the bits in the string, and based on whether or not
// the bit is a 1, we accumulate 2 raised to a certain power.

      int power = original.length() - 1;

      int sum = 0;

      for (int counter = power;counter >= 0;counter--)
         if (original.charAt(original.length()-1-counter) == '1')
            sum += Math.pow(2,counter);

      return(sum);
   }

   public String toString() {
      String line = "\n";
      line += "Original" + "\t";
      line += "QuadraDecimal" + "\t";
      line += "Octal" + "\t";
      line += "Decimal" + "\t";
      line += "Hexadecimal" + "\n";
      line += original + "\t";
      line += quadra + "\t";
      line += octal + "\t";
      line += decimal + "\t";
      line += hexadecimal + "\n";
      return(line);
   }

   public static String equiv(String bit1,String bit2) {
      int tens = new Integer(bit1).intValue();
      int units = new Integer(bit2).intValue();

      int number = 2*tens + units;

      String returnString="";

      switch (number) {
         case 0 : returnString = "0"; break;
         case 1 : returnString = "1"; break;
         case 2 : returnString = "2"; break;
         case 3 : returnString = "3"; break;
      }

      return(returnString);
   }

   public static String equiv(String bit1,String bit2,String bit3) {
      int hundreds = new Integer(bit1).intValue();
      int tens = new Integer(bit2).intValue();
      int units = new Integer(bit3).intValue();

      int number = 4*hundreds + 2*tens + units;

      String returnString = "";

      switch(number) {
         case 0 : returnString = "0"; break;
         case 1 : returnString = "1"; break;
         case 2 : returnString = "2"; break;
         case 3 : returnString = "3"; break;
         case 4 : returnString = "4"; break;
         case 5 : returnString = "5"; break;
         case 6 : returnString = "6"; break;
         case 7 : returnString = "7"; break;
      }

      return(returnString);
   }

   public static String equiv(String bit1,String bit2,String bit3,String bit4) {
      int thousands = new Integer(bit1).intValue();
      int hundreds = new Integer(bit2).intValue();
      int tens = new Integer(bit3).intValue();
      int units = new Integer(bit4).intValue();

      int number = 8*thousands + 4*hundreds + 2*tens + units;

      String returnString = "";

      switch (number) {
         case 0 : returnString = "0"; break;
         case 1 : returnString = "1"; break;
         case 2 : returnString = "2"; break;
         case 3 : returnString = "3"; break;
         case 4 : returnString = "4"; break;
         case 5 : returnString = "5"; break;
         case 6 : returnString = "6"; break;
         case 7 : returnString = "7"; break;
         case 8 : returnString = "8"; break;
         case 9 : returnString = "9"; break;
         case 10 : returnString = "A"; break;
         case 11 : returnString = "B"; break;
         case 12 : returnString = "C"; break;
         case 13 : returnString = "D"; break;
         case 14 : returnString = "E"; break;
         case 15 : returnString = "F"; break;
      }

      return(returnString);
   }

   public static void main(String[] args) {
      Binary myBinary = new Binary("1010");

      System.out.println(myBinary);
   }
}
Recall our discussion of preincrementing and postincrementing.

The value of the expression counter++; is the value of couter before it is incremented.

The value of the expression ++counter; is the value of counter after it is incremented.

Methods

We have used methods a great deal in our programs. Recall that a method is a collection of code which has a name. This gives us the ability to call this code as many times as we want.

Methods give us a great deal of efficiency. They allow us to write a peice of code one time and use it as many times as we need. Recall our laboratory example last week.

import java.io.*;

public class PMT {
  int n;

  public PMT(int n) {
     this.n = n;
  }

  private boolean prime(int n) {
     boolean is_prime = true;

     for (int counter=2;counter < n;counter++)
        if (n % counter == 0)
           is_prime = false;

     return(is_prime);
  }

  public int pi_of_x(int n) {
     int count = 0;

     for (int counter=2;counter <= n;counter++)
        if (prime(counter))
           count++;

     return(count);
  }

  public double x_over_log_x(int n) {
     return(n/Math.log(n));
  }

  public void display() {
     String temp = "";

     for (int counter=2;counter <= n;counter++) {
        temp = "\n" + counter + "\t";
        temp += pi_of_x(counter) + "\t";
        temp += x_over_log_x(counter);
        System.out.println(temp);
    }
  }

  public static void main(String[] args) throws IOException {
    InputStreamReader stream = new InputStreamReader(System.in);
    BufferedReader keyboard = new BufferedReader(stream);

    PMT pMT = new PMT(10);
    pMT.display();

    String s = keyboard.readLine();
  }
}
We wrote the method prime to make pi_of_x easier to code. Otherwise we would have had to written all of the code in prime inside pi_of_x.

Notice that putting the code in a seperate method also allows for a level of abstraction. Instead of being concerned with the details of how to determine whether or not a number is prime, we simply call a method called prime which does the work. So we don't have to be concerned with the details in pi_of_x.

Let's examine in more detail how the parameters work in a method.

Recall that formal parameters are listed in the signature of the method.

For example, in the method signature

public boolean prime(int n),
the formal parameter list is int n.

If there is more than one parameter in the list we seperate them by commas.

For example,

public int power(int base,int exponent)
The way we obtain values from methods is to call them. For example, to call the above method we could use a statement like

int a = power(2,3);
Notice one important thing about this method call. The method call must be used the same way we would use an int. That is, we can use a method that returns type int like an int variable.

For example, the following statement is illegal.

power(2,3);
It is illegal because the method produces an int and we can't simply put an int on a line.

In this example 2 and 3 are called actual parameters. They must match in position and type to the formal parameters in the method signature.

Objects are valid parameter types. So that means that we can have some interesting calls to methods because everything is of type Object.

Recall the ways we had of inputting data from the keyboard.

We first created an object called stream of type InputStreamReader.

InputStreamReader stream = new InputStreamReader(System.in);
Then we declared an object called keyboard of type BufferedReader.

BufferedReader keyboard = new BufferedReader(stream);
The constructor that is being called in the BufferedReader class actually requires a formal parameter of type Reader. Why doesn't the compiler complain? The reason is inheritance.

The class InputStreamReader inherits from the class Reader and so is of type Reader.

There is a class called FileReader which inherits from type InputStreamReader. So it is actually of type InputStreamReader and of type Reader. So any object of type FileReader is a valid parameter to BufferedReader.

We can use the class FileReader to read from an external file.