Difference between revisions of "Binary Nums"

From CompSciWiki
Jump to: navigation, search
m (-take)
m (HTML to wiki format)
 
(16 intermediate revisions by 3 users not shown)
Line 9: Line 9:
 
How are all numbers represented in 0s and 1s?
 
How are all numbers represented in 0s and 1s?
  
<ul>
+
* Instead of having digits 0,1,...,9, in binary, we only have digits 0 and 1.
<li>Instead of having digits 0,1,...,9, in binary, we only have digits 0 and 1.</li>
+
* So zero is 0, and the next number is represented by 1, but after that, we have no digit 2, so we have to represent the next number in the same way we do after we go past 9 in the decimal system: by 10.
<li>So zero is 0, and the next number is represented by 1, but after that, we have no digit 2, so we have to represent the next number in the same way we do after we go past 9 in the decimal system: by 10.</li>
+
* We continue in this way: 3 in binary is 11.
<li>We continue in this way: 3 in binary is 11.</li>
+
* Now what about 4? We can’t write 4 as 12 (because we only have 1 and 0 to work with, not 2). So we put a zero in the last position, and carry the 1. This would give 20, but again, we don’t have a digit 2, so we again carry the 1 and get 100 as the binary representation of 4.
<li>Now what about 4? We can’t write 4 as 12 (because we only have 1 and 0 to work with, not 2). So we put a zero in the last position, and carry the 1. This would give 20, but again, we don’t have a digit 2, so we again carry the 1 and get 100 as the binary representation of 4.</li>
+
 
</ul>
+
  
 
Here are the first few numbers written in both decimal (normal) notation and binary:
 
Here are the first few numbers written in both decimal (normal) notation and binary:
 
 
 
 
<table border = 1>
 
<table border = 1>
 
<tr>
 
<tr>
Line 49: Line 45:
 
<td>1011</td>
 
<td>1011</td>
 
</tr>
 
</tr>
 
 
</table>
 
</table>
 +
  
 
Suppose we have a binary number (a sequence of zeroes and ones) and we want to convert it to a decimal number. To do this, we multiply the digit (0 or 1) in each position of the number by an increasing power of two
 
Suppose we have a binary number (a sequence of zeroes and ones) and we want to convert it to a decimal number. To do this, we multiply the digit (0 or 1) in each position of the number by an increasing power of two
Line 59: Line 55:
  
 
=Program Specifications=
 
=Program Specifications=
<ul>
+
 
<li>Write a program that takes input as an integer, interprets it as a binary number, and prints out its value as a decimal number.
+
* Write a program that requests input as a binary integer and prints out its value as a decimal number.
</li><li> Get input using Scanner.
+
* Get input using Scanner.
</li><li> Use integer division and remainder to extract digits from the input binary number.
+
* Use integer division and remainder to extract digits from the input binary number.
</li><li> Assume the user only inputs numbers with digits 0 and 1.
+
* Assume the user only inputs numbers with digits 0 and 1, so no error checking is needed.
</li><li> Use a loop so the user can continue to input binary numbers until they input -1 , then exit.
+
* Use a loop so the user can continue to input binary numbers until they input -1 , then exit.
</li><li> Here is a sample run of the program:
+
* Here is a sample run of the program with output:
<pre>
+
 
Enter a binary number:1001010
+
Enter a binary number:1001010
1001010 in decimal is 74.
+
1001010 in decimal is 74.
Enter a binary number:1001111
+
Enter a binary number:1001111
1001111 in decimal is 79.
+
1001111 in decimal is 79.
Enter a binary number:10000111
+
Enter a binary number:10000111
10000111 in decimal is 135.
+
10000111 in decimal is 135.
Enter a binary number:-1
+
Enter a binary number:-1
Programmed by [your name here].
+
Programmed by [your name here].
End of processing.
+
End of processing.
</pre>
+
</li></ul>
+
  
 
==Output==
 
==Output==
Use System.out for output. Follow the format of the output shown above.  
+
Use System.out.println() for output. Follow the format of the output shown above.  
  
You may notice that your program fails for large numbers. That's because of integer overflow. If you would like to get your program to work for larger binary numbers, replace int with long in your program (including using the Scanner method nextLong()).
+
'''Note for further development:''' You may notice that your program fails for large numbers. That's because of integer overflow. If you would like to get your program to work for larger binary numbers, replace int with long in your program (including using the Scanner method nextLong()).
  
 
|Solution=  
 
|Solution=  
The greatest ways to start a problem is to divide it into smaller problems. Clearly, the main problem to solve is converting binary numbers to decimal numbers. Input using the scanner class and looping for more input are the other two sub-problems.
+
The greatest way to start a problem is to divide it into smaller problems. Clearly, the main problem to solve is converting binary numbers to decimal numbers. Think of input using the scanner class and looping for more input as the other two sub-problems. You can divide a problem any way you see fit; I've decided to break this problem into three parts:
  
===Determine how to Convert from Binary Numbers to Decimal Numbers===
+
* converting binary numbers to decimal numbers
 +
* input using the scanner class
 +
* looping for more input
  
So you don't know how to convert binary numbers to decimal
+
The first part of the solution shows how to convert from binary numbers to decimal numbers going from pseudocode to working Java code. The second part shows how to use the scanner class to obtain input from the terminal. The third part shows how to add a loop to your code in order to keep prompting the user for input. Let's start by solving the main problem.  
numbers. That is fine. You can figure it out.
+
  
To solve the problem, we will initially forget about
 
writing good java code, and instead use anything simpler.
 
We can draw diagrams, write equations, and write pseudocode. We can
 
always write java code after we understand how to solve the problem.
 
  
The first thing to do is gather information from the problem specification.
+
==Convert from Binary Numbers to Decimal Numbers==
In it we were told:
+
On our road to a solution, we will take a detour and forget about writing Java code. Instead we will use something simpler. We can draw diagrams, write equations, and write pseudocode. We can always write Java code once we understand how to solve the problem. However, let’s go completely off track, and make sure we understand what binary numbers and decimal numbers are.
  
 +
Numbers are not all the same. Human beings have used many different number systems throughout the ages. People today are used to decimal numbers, but this wasn’t always so. Decimal numbers are base 10, and some people may say it makes sense because we usually count with 10 fingers. However, we have 12 months in a year rather than 10, and 7 days in a week not 10. Decimal numbers are the numbers you are used to. We use 1,2,3,4,5,6,7,8,9, to represent values and 0 as a place-holder and to represent no amount. Before we can understand the binary system, let’s understand how the decimal system works.
  
The value of the binary number 1011001 is
+
You know intuitively that 123 is one-hundred and twenty-three, and you have a good idea of what that means. However, to understand decimal in depth, you’ll want to be able to explain it mathematically.
  
'''1''' * 2^6 + '''0''' * 2^5 + '''1''' * 2^4 + '''1''' * 2^3 + '''0''' * 2^2 + '''0''' * 2^1 + '''1''' * 2^0 = 89
+
123 = 3 + 2* 10 + 1 * 100
 +
This is better represented as:
 +
123 = 3 * 10^0 + 2* 10^1 + 1 * 10^2
 +
 
 +
Now that we have explained how decimal numbers work, it is time to explain binary numbers. Binary numbers work exactly as decimal works except instead of 10, we use 2. And we only use the digits 0 and 1.
 +
 
 +
The binary number 100 means:
 +
100 = 0 + 0* 2 + 1 * 4
 +
This is better represented as:
 +
100 = 0 * 2^0 + 0* 2^1 + 1 * 2^2
 +
 
 +
However, the best way to be sure we know how to convert the binary numbers to decimal numbers is to do it.
 +
Let's check that we understand by converting some numbers from binary to decimal on paper. By solving the problem on paper, we can more easily see the steps. Convert the following numbers from binary to decimal on paper: 101, 1000, 1101, 10101. When you are done, check for the solution at the end of this case study (in Solutions to Exercises). The solution to the first number follows:
  
If we look at this carefully, we see that the right most digit of the binary number is multiplied by 2^0. The second left most
 
digit is multiplied by 2^1. The digit to the right of that is multiplied by 2^2 and so on. Finally, all those products are summed up.
 
  
However, we need to make sure we are correct. Let's check that we understand by converting some of the following numbers from binary to decimal.  
+
  100
 +
  Convert to decimal.
 +
  Start at rightmost digit.
 +
  0 * 2^0 = 0
 +
  0 * 2^1 = 0
 +
  1 * 2^2 = 4
 +
  answer: 0 + 0 + 4 = 4. 100 in binary is 4 in decimal.
  
0, 1, 10, 11, 101, 1000, 1101, 10101
+
The next step is to describe the steps you used. This will be your pseudocode. Do not focus on writing Java-like pseudocode, start by writing it out in English. I started with the following pseudocode:
  
Now, try to write some pseudocode to explain how we solved this problem. We will later shape this into Java code.
 
  
<pre>
+
1. Take the rightmost digit,  
1. take the rightmost digit,  
+
 
       if it is a 1, multiply it by 2 to the power of the current exponent and add it to the sum.
 
       if it is a 1, multiply it by 2 to the power of the current exponent and add it to the sum.
2. do the same with digits to the left of the rightmost digit.
+
2. Do the same with digits to the left of the rightmost digit.
</pre>
+
  
A little bit more thinking shows we need to tell what sum, and what exponent to start at. Anything multiplied
+
More thinking shows we need to tell what sum, and what exponent to start at. Let's also add variables for clarity.
by zero is zero, so we can simplify the pseudocode. Let's also add variables for clarity.
+
  
<pre>
+
  currPower = 0
  exponent = 0
+
 
  sum = 0
 
  sum = 0
  
  take the rightmost digit ''d'',
+
  Take the rightmost digit currDigit.
      sum = sum + d * 2^exponent
+
if currDigit == 1
  do the same with digits to the left of the rightmost digit.
+
    sum = sum + currDigit * 2 ^ currPower
</pre>
+
  Do the same with digits to the left of the rightmost digit.
  
  
==Convert to Java-like Pseudocode==
+
In the problem specification, you may have read: "Use integer division and remainder to extract digits from the input binary number." This command is a very vague description of how to process the input number. Let's look at how to do this in more detail.
  
===How do I extract the rightmost digit?===
+
=====Use Modulus=====
In Java, you have some basic arithmetic operators, you can multiply (using *),
+
In Java, you can use some basic arithmetic operators, you can multiply,
divide (using /), add (+), subtract (-), and get the remainder (%).  
+
divide, add, subtract, and [http://www.cafeaulait.org/course/week2/15.html obtain the remainder].  
  
If you can define what the rightmost digit is using the above operations you
+
Perhaps you expect me to teach about the extract-rightmost-digit operator. Unfortunately,
can easily determine what it is.  
+
it does not exist. We need to use the basic arithmetic operators to do our bidding. Fortunately, there's a solution for that.  
  
The rightmost digit of a number is the exact same thing as the remainder of
+
The rightmost digit of a number is the exact same thing as the remainder of a number divided by 10. For example, the remainder of 26 divided by 10 is 6. In Java, we would write 26 % 10 to do the same operation.
a number divided by 10.  
+
For example, the remainder of 26 divided by 10 is 6. In Java, we would write
+
26 % 10 to do the same operation.
+
  
===How do I ignore the rightmost digit?===
+
=====Use Integer Division=====
  
So you want to convert 321 to 32.  
+
In order to go through the number digit-by-digit, from right to left, you will want to ignore the rightmost digit. How do we do this?
  
Recall, that in Java the division of two integers ignores any fractions.
+
Recall that Java allows for '''integer division'''. This means the division of two integers ignores any fractions. So 3/2 evaluates to 1 in Java although it equals 1.5 in regular math.  
So 3/2 =1, in Java code although it equals 1.5 in regular math. The way java calculates
+
the quotient is called integer division.
+
  
To chop off the rightmost digit, we simply do integer divide by 10.  
+
To chop off the rightmost digit, we simply divide by 10. In Java, we would write 26 /10 and the result would be 2, not 2.6.  
In Java, we would write 26 /10 and the result would be 2.
+
  
  
== Transform the Pseudocode into Java Code==
 
 
You can continue improving the pseudocode slightly until you have replaced much of the English instructions with Java-like code.
 
You can continue improving the pseudocode slightly until you have replaced much of the English instructions with Java-like code.
 
Here is an example of my result.
 
Here is an example of my result.
  
<pre>
+
  currPower = 0
  exponent = 0
+
 
  sum = 0
 
  sum = 0
 
   
 
   
 
  while (binaryNum!= 0)
 
  while (binaryNum!= 0)
 
  {
 
  {
     rightmost = binaryNum % 10  //right most digit  
+
     currDigit = binaryNum % 10  //right most digit  
     sum = sum + rightmost * 2^exponent
+
     sum = sum + currDigit * 2 ^ currPower
 
     binaryNum = binaryNum / 10 //do the same with the digits to the left of the rightmost digit
 
     binaryNum = binaryNum / 10 //do the same with the digits to the left of the rightmost digit
 
  }
 
  }
</pre>
+
//This code has syntax errors
  
Now that you have some code, let's make sure that it is sound. Let's run it through the compiler.
+
Now that you have some code, let's make sure that it is sound. Let's compile it.
  
==Create the Structure of the Program==
 
  
Now create a Java file.
+
Create a Java file.
  
 
Define the class in a Java file.
 
Define the class in a Java file.
Line 187: Line 181:
  
 
The following code shows the result of these steps.
 
The following code shows the result of these steps.
<pre>
+
public class BinaryNum
public class BinaryNum
+
{
{
+
  public static void main(String[] args)
  public static void main(String[] args)
+
  {
  {
+
  }
  }
+
}
}
+
 
</pre>
+
  
==Test your Code==
 
 
Take the code for converting numbers, and paste
 
Take the code for converting numbers, and paste
 
it into the main method. Then compile it and fix any errors. You may
 
it into the main method. Then compile it and fix any errors. You may
 
need to add semicolons, and declare variables.
 
need to add semicolons, and declare variables.
  
You will need to add an output statement so you can test your results.
+
You will need to add an output statement so you can see the results.
As for input, just set the binaryNum variable in the code for now (this is called hardcoded input).
+
As for input, just set the binaryNum variable in the code for now (this is called '''hardcoded input''').
  
<pre>
+
public class BinaryNum
public class BinaryNum
+
{
{
+
 
   public static void main(String[] args)
 
   public static void main(String[] args)
 
   {
 
   {
 
     int binaryNum = 101;  //hardcoded input
 
     int binaryNum = 101;  //hardcoded input
     int exponent = 0;
+
     int currPower = 0;
 
     int sum = 0;
 
     int sum = 0;
 
   
 
   
 
     while (binaryNum!= 0)
 
     while (binaryNum!= 0)
 
     {
 
     {
       rightmost = binaryNum % 10  //right most digit  
+
       currDigit= binaryNum % 10  //right most digit  
       sum = sum + rightmost * 2^exponent;
+
       if (currDigit == 1)
 +
      {
 +
        sum = sum + currDigit* 2 ^ currPower;
 +
      }
 
       binaryNum = binaryNum / 10; //do the same with the digits to the left of the rightmost digit
 
       binaryNum = binaryNum / 10; //do the same with the digits to the left of the rightmost digit
 
     }
 
     }
 
     System.out.println(binaryNum + "in decimal is " + sum);
 
     System.out.println(binaryNum + "in decimal is " + sum);
 
   }
 
   }
}
+
}
</pre>
+
  
==Fix your Code==
 
For me trying to compile my code resulted in the need to fix a few small syntactical errors.
 
  
Once I ran my code, the output was strange. 0 in decimal is 4. Hmm, that cannot be right. Whenever a program does this,
 
a computer scientist can do one of two things, only one of them is rational. He or she can get angry at the computer,
 
and say things like -it should work. Or he or she can accept that their code is incorrect, and try to see where it is incorrect.
 
However, it can be difficult to see where you went wrong. The same type of thinking that produced the error cannot be used to see the error.
 
  
You need to think like the machine to see the error. Go through your code line by line, and determine what went wrong. You can either do this mentally, insert print statements to print out the values of the variable, or you can use a debugger.
+
You are likely to discover small syntactical errors when you try to compile your code. After successfully compiling, you might find that the program gives incorrect output. Then, you will need to accept that your code is incorrect, and try to determine the problem. However, it can be difficult to see the mistake if the same type of thinking that produced the error is used to see the error.  You need to think like the machine to see the error. Go through your code line by line, and determine what went wrong.  
  
The problem with my code, was that I destroyed the value of my input. While calculating the value of the decimal number, my program eventually sets the input ''binaryNum'' to zero. The simple solution is to add another variable to store a copy of the input, and print out the original.
+
After fixing my code I had the following main method:
  
The result is the following code
+
public static void main(String[] args)
 +
{
 +
  int binaryNum = 101;  //hardcoded input
 +
  int currPower = 0;
 +
  int sum = 0;
 +
  int currDigit;
 +
  int copyOfBinNum = binaryNum;
 +
 +
  while (copyOfBinNum!= 0)
 +
  {
 +
    currDigit = copyOfBinNum % 10;  //right most digit
 +
    sum = (int) (sum + currDigit * Math.pow(2, currPower));
 +
    copyOfBinNum = copyOfBinNum / 10;
 +
    currPower = currPower + 1;
 +
  }
 +
  System.out.println(binaryNum + " in decimal is " + sum);
 +
}
  
<pre>
 
  public static void main(String[] args)
 
  {
 
    int binaryNum = 101;  //hardcoded input
 
    int exponent = 0;
 
    int sum = 0;
 
    int rightmost;
 
    int copyOfBinNum = binaryNum;
 
  
    while (copyOfBinNum!= 0)
+
Now test your code with different values of binaryNum. Be sure to recompile after changing your code and before testing it. Once you are satisfied, that your code correctly converts binary numbers to decimal numbers move to the next step.
    {
+
      rightmost = copyOfBinNum % 10;  //right most digit
+
      sum = sum + rightmost * 2^exponent;
+
      copyOfBinNum = copyOfBinNum / 10; //do the same with the digits to the left of the rightmost digit
+
    }
+
    System.out.println(binaryNum + " in decimal is " + sum);
+
  }
+
  
</pre>
+
==Handle Input==
 +
To handle input, we are going to use the scanner class. To use the scanner class we have to import it first. Classes often provide useful methods. By importing a class, we gain access to these methods. For a more detailed instructions on how to use the scanner class read [[Input_using_Scanner ]].
  
Now test your code with different values for binaryNum. Don't forget to recompile after changing your code. Once you are satisfied,
+
Import the scanner class. Do this by including the following line at the top of the Java file, before the class definition. The line tells the compiler where to find the scanner class.
that your code correctly converts binary numbers to decimal numbers move to the next step.
+
  
==Determine how to input the number==
+
import java.util.Scanner;
  ===Import the Scanner Class===
+
 
The problem specification says we need to use scanner.  
+
Declare and instantiate the scanner class. Because we want to read from the terminal as opposed to a file, instantiate the scanner class with System.in as a parameter. System.in represents the terminal. You can give the scanner class any name that is a valid identifier; you don’t have to use “aScanner”.
  ===Use the Correct Method===
+
 
 +
Scanner aScanner = new Scanner(System.in);
 +
 
 +
Now that we have an instance of the scanner in the code we need to decide how to use it. Before we can choose which method to use, we need to decide how we want to store our input. Storing the numbers as a string would prevent us from being able to use remainder and integer division to convert the number to binary. We must store the number as an integer.
 +
 
 +
However, there are two types of primitive integer types: int and long. A long is a primitive type for storing integers with twice as much storage space (from -2^64 to (2^64)-1), where as an int goes from -2^32 to (2^32)-1). Longs store larger integer values than int. For this example, you should store the inputted number as a long. By storing the number as a long we are less likely to encounter the problem of overflow. Overflow is exactly like it sounds, the number is too big for the variable to store.
 +
 
 +
You will have to declare the variable that stores the input as a long instead of an int, thus:
 +
 
 +
long binaryNumber
 +
 
 +
Once you have chosen what type of variable to store the input in, choosing the appropriate input method is trivial. If you decided to store the input as a long, use the nextLong() method in order to read in a long from the terminal. If you decided to store the input as an int, use the nextInt() method. The following line shows how to store the input in your input variable using the Scanner class.
 +
 
 +
binaryNumber = aScanner.nextLong();
 +
 
 +
Finally, we need to replace the hardcoded input with actual input. The only reason we used hardcoded input is to allow us to test our program before we implement input. In this case, hardcoded input is a form of scaffolding, a part of the code you use when developing, but that is not part of the final product.  So get rid of the hardcoded input.
 +
 
 +
Replace the following line:
 +
  int binaryNumber = 101;  //hardcoded input
 +
 
 +
with
 +
 
 +
binaryNumber = aScanner.nextLong();
  
  
 
== Add a Loop ==
 
== Add a Loop ==
  ===Determine the Kind of Loop===
+
From the program specification, we know that we need a [[loop]].
  ===Determine the Termination Condition===
+
 
 +
Determine the kind of loop. The two types of loops are for-loops and while-loops. Use a for-loop if you can determine in advance, how many times the loop will run. For example, if you need to print out each element in an array then use a for-loop.
 +
In this case, we do not know how many times the user will input binary numbers. Therefore, use a while-loop.
 +
 
 +
Specify the termination condition of the loop. From the program specification, we know we need to stop when the user inputs -1. Expressed using the word while, we need to continue prompting for input while the input is not -1.
 +
 
 +
while(binaryNumber != -1)
 +
{
 +
  //place code to repeat here
 +
}
 +
 
  
 +
==Solution to Exercises==
 +
101 = 5, 1000 = 8, 1101 = 13, 10101 = 21.
  
 
|SolutionCode=import java.util.Scanner;
 
|SolutionCode=import java.util.Scanner;
Line 333: Line 355:
  
  
|SideSectionTitle=
+
|SideSectionTitle=Numbers
 
|SideSection=
 
|SideSection=
 +
[[Image:Number_casestudy.jpg|center]]<BR>
  
 
}}
 
}}

Latest revision as of 19:07, 4 April 2011

Back to the Case Studies homepage

Problem

As you may know, computers work on the binary system. In this system, numbers are written using only 0s and 1s. In this question, you’ll write a program to convert binary numbers to normal (decimal) numbers.

How are all numbers represented in 0s and 1s?

  • Instead of having digits 0,1,...,9, in binary, we only have digits 0 and 1.
  • So zero is 0, and the next number is represented by 1, but after that, we have no digit 2, so we have to represent the next number in the same way we do after we go past 9 in the decimal system: by 10.
  • We continue in this way: 3 in binary is 11.
  • Now what about 4? We can’t write 4 as 12 (because we only have 1 and 0 to work with, not 2). So we put a zero in the last position, and carry the 1. This would give 20, but again, we don’t have a digit 2, so we again carry the 1 and get 100 as the binary representation of 4.


Here are the first few numbers written in both decimal (normal) notation and binary:

decimal 1 2 3 4 5 6 7 8 9 10 11
binary 1 10 11 100 101 110 111 1000 1001 1010 1011


Suppose we have a binary number (a sequence of zeroes and ones) and we want to convert it to a decimal number. To do this, we multiply the digit (0 or 1) in each position of the number by an increasing power of two the further we move left. So the value of the binary number 1011001 is

1 * 2^6 + 0 * 2^5 + 1 * 2^4 + 1 * 2^3 + 0 * 2^2 + 0 * 2^1 + 1 * 2^0 = 89


Program Specifications

  • Write a program that requests input as a binary integer and prints out its value as a decimal number.
  • Get input using Scanner.
  • Use integer division and remainder to extract digits from the input binary number.
  • Assume the user only inputs numbers with digits 0 and 1, so no error checking is needed.
  • Use a loop so the user can continue to input binary numbers until they input -1 , then exit.
  • Here is a sample run of the program with output:
Enter a binary number:1001010
1001010 in decimal is 74.
Enter a binary number:1001111
1001111 in decimal is 79.
Enter a binary number:10000111
10000111 in decimal is 135.
Enter a binary number:-1
Programmed by [your name here].
End of processing.

Output

Use System.out.println() for output. Follow the format of the output shown above.

Note for further development: You may notice that your program fails for large numbers. That's because of integer overflow. If you would like to get your program to work for larger binary numbers, replace int with long in your program (including using the Scanner method nextLong()).

 

Numbers

Number casestudy.jpg

Solution

The greatest way to start a problem is to divide it into smaller problems. Clearly, the main problem to solve is converting binary numbers to decimal numbers. Think of input using the scanner class and looping for more input as the other two sub-problems. You can divide a problem any way you see fit; I've decided to break this problem into three parts:

  • converting binary numbers to decimal numbers
  • input using the scanner class
  • looping for more input

The first part of the solution shows how to convert from binary numbers to decimal numbers going from pseudocode to working Java code. The second part shows how to use the scanner class to obtain input from the terminal. The third part shows how to add a loop to your code in order to keep prompting the user for input. Let's start by solving the main problem.


Convert from Binary Numbers to Decimal Numbers

On our road to a solution, we will take a detour and forget about writing Java code. Instead we will use something simpler. We can draw diagrams, write equations, and write pseudocode. We can always write Java code once we understand how to solve the problem. However, let’s go completely off track, and make sure we understand what binary numbers and decimal numbers are.

Numbers are not all the same. Human beings have used many different number systems throughout the ages. People today are used to decimal numbers, but this wasn’t always so. Decimal numbers are base 10, and some people may say it makes sense because we usually count with 10 fingers. However, we have 12 months in a year rather than 10, and 7 days in a week not 10. Decimal numbers are the numbers you are used to. We use 1,2,3,4,5,6,7,8,9, to represent values and 0 as a place-holder and to represent no amount. Before we can understand the binary system, let’s understand how the decimal system works.

You know intuitively that 123 is one-hundred and twenty-three, and you have a good idea of what that means. However, to understand decimal in depth, you’ll want to be able to explain it mathematically.

123 = 3 + 2* 10 + 1 * 100
This is better represented as:
123 = 3 * 10^0 + 2* 10^1 + 1 * 10^2

Now that we have explained how decimal numbers work, it is time to explain binary numbers. Binary numbers work exactly as decimal works except instead of 10, we use 2. And we only use the digits 0 and 1.

The binary number 100 means:
100 = 0 + 0* 2 + 1 * 4
This is better represented as:
100 = 0 * 2^0 + 0* 2^1 + 1 * 2^2

However, the best way to be sure we know how to convert the binary numbers to decimal numbers is to do it. Let's check that we understand by converting some numbers from binary to decimal on paper. By solving the problem on paper, we can more easily see the steps. Convert the following numbers from binary to decimal on paper: 101, 1000, 1101, 10101. When you are done, check for the solution at the end of this case study (in Solutions to Exercises). The solution to the first number follows:


 100 
 Convert to decimal.
 Start at rightmost digit.
 0 * 2^0 = 0
 0 * 2^1 = 0
 1 * 2^2 = 4
 answer: 0 + 0 + 4 = 4. 100 in binary is 4 in decimal.

The next step is to describe the steps you used. This will be your pseudocode. Do not focus on writing Java-like pseudocode, start by writing it out in English. I started with the following pseudocode:


1. Take the rightmost digit, 
      if it is a 1, multiply it by 2 to the power of the current exponent and add it to the sum.
2. Do the same with digits to the left of the rightmost digit.

More thinking shows we need to tell what sum, and what exponent to start at. Let's also add variables for clarity.

currPower = 0
sum = 0
Take the rightmost digit currDigit. 
if currDigit == 1
   sum = sum + currDigit * 2 ^ currPower
Do the same with digits to the left of the rightmost digit.


In the problem specification, you may have read: "Use integer division and remainder to extract digits from the input binary number." This command is a very vague description of how to process the input number. Let's look at how to do this in more detail.

Use Modulus

In Java, you can use some basic arithmetic operators, you can multiply, divide, add, subtract, and obtain the remainder.

Perhaps you expect me to teach about the extract-rightmost-digit operator. Unfortunately, it does not exist. We need to use the basic arithmetic operators to do our bidding. Fortunately, there's a solution for that.

The rightmost digit of a number is the exact same thing as the remainder of a number divided by 10. For example, the remainder of 26 divided by 10 is 6. In Java, we would write 26 % 10 to do the same operation.

Use Integer Division

In order to go through the number digit-by-digit, from right to left, you will want to ignore the rightmost digit. How do we do this?

Recall that Java allows for integer division. This means the division of two integers ignores any fractions. So 3/2 evaluates to 1 in Java although it equals 1.5 in regular math.

To chop off the rightmost digit, we simply divide by 10. In Java, we would write 26 /10 and the result would be 2, not 2.6.


You can continue improving the pseudocode slightly until you have replaced much of the English instructions with Java-like code. Here is an example of my result.

currPower = 0
sum = 0

while (binaryNum!= 0)
{
    currDigit = binaryNum % 10  //right most digit 
    sum = sum + currDigit * 2 ^ currPower
    binaryNum = binaryNum / 10 //do the same with the digits to the left of the rightmost digit
}
//This code has syntax errors

Now that you have some code, let's make sure that it is sound. Let's compile it.


Create a Java file.

Define the class in a Java file. Name the file the same name as the class name plus the ".java" extension. Define the main method.

The following code shows the result of these steps.

public class BinaryNum
{
  public static void main(String[] args)
  {
  }
}


Take the code for converting numbers, and paste it into the main method. Then compile it and fix any errors. You may need to add semicolons, and declare variables.

You will need to add an output statement so you can see the results. As for input, just set the binaryNum variable in the code for now (this is called hardcoded input).

public class BinaryNum
{
 public static void main(String[] args)
 {
   int binaryNum = 101;  //hardcoded input
   int currPower = 0;
   int sum = 0;

   while (binaryNum!= 0)
   {
     currDigit= binaryNum % 10  //right most digit 
     if (currDigit == 1)
     {
       sum = sum + currDigit* 2 ^ currPower;
     }
     binaryNum = binaryNum / 10; //do the same with the digits to the left of the rightmost digit
   }
   System.out.println(binaryNum + "in decimal is " + sum);
 }
}


You are likely to discover small syntactical errors when you try to compile your code. After successfully compiling, you might find that the program gives incorrect output. Then, you will need to accept that your code is incorrect, and try to determine the problem. However, it can be difficult to see the mistake if the same type of thinking that produced the error is used to see the error. You need to think like the machine to see the error. Go through your code line by line, and determine what went wrong.

After fixing my code I had the following main method:

public static void main(String[] args)
{
  int binaryNum = 101;  //hardcoded input
  int currPower = 0;
  int sum = 0;
  int currDigit;
  int copyOfBinNum = binaryNum;

  while (copyOfBinNum!= 0)
  {
    currDigit = copyOfBinNum % 10;  //right most digit
    sum = (int) (sum + currDigit * Math.pow(2, currPower));
    copyOfBinNum = copyOfBinNum / 10; 
    currPower = currPower + 1;
  }
  System.out.println(binaryNum + " in decimal is " + sum);
}


Now test your code with different values of binaryNum. Be sure to recompile after changing your code and before testing it. Once you are satisfied, that your code correctly converts binary numbers to decimal numbers move to the next step.

Handle Input

To handle input, we are going to use the scanner class. To use the scanner class we have to import it first. Classes often provide useful methods. By importing a class, we gain access to these methods. For a more detailed instructions on how to use the scanner class read Input_using_Scanner .

Import the scanner class. Do this by including the following line at the top of the Java file, before the class definition. The line tells the compiler where to find the scanner class.

import java.util.Scanner;

Declare and instantiate the scanner class. Because we want to read from the terminal as opposed to a file, instantiate the scanner class with System.in as a parameter. System.in represents the terminal. You can give the scanner class any name that is a valid identifier; you don’t have to use “aScanner”.

Scanner aScanner = new Scanner(System.in);

Now that we have an instance of the scanner in the code we need to decide how to use it. Before we can choose which method to use, we need to decide how we want to store our input. Storing the numbers as a string would prevent us from being able to use remainder and integer division to convert the number to binary. We must store the number as an integer.

However, there are two types of primitive integer types: int and long. A long is a primitive type for storing integers with twice as much storage space (from -2^64 to (2^64)-1), where as an int goes from -2^32 to (2^32)-1). Longs store larger integer values than int. For this example, you should store the inputted number as a long. By storing the number as a long we are less likely to encounter the problem of overflow. Overflow is exactly like it sounds, the number is too big for the variable to store.

You will have to declare the variable that stores the input as a long instead of an int, thus:

long binaryNumber

Once you have chosen what type of variable to store the input in, choosing the appropriate input method is trivial. If you decided to store the input as a long, use the nextLong() method in order to read in a long from the terminal. If you decided to store the input as an int, use the nextInt() method. The following line shows how to store the input in your input variable using the Scanner class.

binaryNumber = aScanner.nextLong();

Finally, we need to replace the hardcoded input with actual input. The only reason we used hardcoded input is to allow us to test our program before we implement input. In this case, hardcoded input is a form of scaffolding, a part of the code you use when developing, but that is not part of the final product. So get rid of the hardcoded input.

Replace the following line:

int binaryNumber = 101;  //hardcoded input

with

binaryNumber = aScanner.nextLong();


Add a Loop

From the program specification, we know that we need a loop.

Determine the kind of loop. The two types of loops are for-loops and while-loops. Use a for-loop if you can determine in advance, how many times the loop will run. For example, if you need to print out each element in an array then use a for-loop. In this case, we do not know how many times the user will input binary numbers. Therefore, use a while-loop.

Specify the termination condition of the loop. From the program specification, we know we need to stop when the user inputs -1. Expressed using the word while, we need to continue prompting for input while the input is not -1.

while(binaryNumber != -1)
{
  //place code to repeat here
}


Solution to Exercises

101 = 5, 1000 = 8, 1101 = 13, 10101 = 21.

Code

Solution Code

Back to the Case Studies homepage