## Solution for

Programming Exercise 9.2

THIS PAGE DISCUSSES ONE POSSIBLE SOLUTION to the following exercise from this on-line Java textbook.

As discussed in Section 1, values of typeintare limited to 32 bits. Integers that are too large to be represented in 32 bits cannot be stored in anintvariable. Java has a standard class,java.math.BigInteger, that addresses this problem. An object of typeBigIntegeris an integer that can be arbitrarily large. (The maximum size is limited only by the amount of memory on your computer.) SinceBigIntegersare objects, they must be manipulated using instance methods from theBigIntegerclass. For example, you can't add twoBigIntegerswith the+operator. Instead, ifNandMare variables that refer toBigIntegers, you can compute the sum ofNandMwith the function callN.add(M). The value returned by this function is a newBigIntegerobject that is equal to the sum ofNandM.The

BigIntegerclass has a constructornew BigInteger(str), wherestris a string. The string must represent an integer, such as "3" or "39849823783783283733". If the string does not represent a legal integer, then the constructor throws aNumberFormatException.There are many instance methods in the

BigIntegerclass. Here are a few that you will find useful for this exercise. Assume thatNandMare variables of typeBigInteger.

N.add(M)-- a function that returns aBigIntegerrepresenting the sum ofNandM.

N.multiply(M)-- a function that returns aBigIntegerrepresenting the result of multiplyingNtimesM.

N.divide(M)-- a function that returns aBigIntegerrepresenting the result of dividingNbyM.

N.signum()-- a function that returns an ordinaryint. The returned value represents the sign of the integerN. The returned value is 1 ifNis greater than zero. It is -1 ifNis less than zero. And it is 0 ifNis zero.

N.equals(M)-- a function that returns abooleanvalue that istrueifNandMhave the same integer value.

N.toString()-- a function that returns aStringrepresenting the value ofN.

N.testBit(k)-- a function that returns abooleanvalue. The parameterkis an integer. The return value istrueif thek-th bit inNis 1, and it isfalseif thek-th bit is 0. Bits are numbered from right to left, starting with 0. Testing "if (N.testBit(0))" is an easy way to check whetherNis even or odd.N.testBit(0)istrueif and only ifNis an odd number.For this exercise, you should write a program that prints

3N+1sequences with starting values specified by the user. In this version of the program, you should useBigIntegersto represent the terms in the sequence. You can read the user's input into aStringwith theTextIO.getln()function. Use the input value to create theBigIntegerobject that represents the starting point of the3N+1sequence. Don't forget to catch and handle theNumberFormatExceptionthat will occur if the user's input is not a legal integer! You should also check that the input number is greater than zero.If the user's input is legal, print out the

3N+1sequence. Count the number of terms in the sequence, and print the count at the end of the sequence. Exit the program when the user inputs an empty line.

Discussion

My solution uses a subroutine,

printThreeNSequence(N), to print out the3N+1sequence starting from theBigInteger,N. The subroutine assumes thatNis notnulland that it represents a value that is greater than one. (These conditions are ensured by the main program which calls the subroutine.) Given these assumptions, the subroutine cannot generate any errors. The only interesting aspect of the subroutine is that all operations on theNmust be performed using instance methods from theBigIntegerclass. For example, to multiplyNby 2, I use a statement "N = N.multiply(TWO);", whereTWOis aBigIntegerthat represents the integer 2. My program definesTWOas a constant, along with several otherBigIntegersthat represent values that I need:static final BigInteger THREE = new BigInteger("3"); static final BigInteger ONE = new BigInteger("1"); static final BigInteger TWO = new BigInteger("2");With these constants, the code for computing the next term in a

3N+1sequence becomes:if (N.testBit(0) == false) { // N is even. Divide N by 2. N = N.divide(TWO); } else { // N is odd. Multiply N by 3, then add 1. N = N.multiply(THREE); N = N.add(ONE); }You can find the complete subroutine in the solution that is given below.

In the

main()routine, the user's input is read into a variable,line, of typeString. The input is used to construct aBigIntegerwith the statement "N = new BigInteger(line);". Since this statement can produce aNumberFormatException, it is placed in atrystatement that can catch and handle the error. The test "if (N.signum() == 1)" is used to make sure thatN >= 1. The value ofN.signum()is 1 if and only ifNis a positive integer. Here is the loop form themain()routine that processes the users input:while (true) { TextIO.putln(); TextIO.putln("Enter the starting value, or press return to end."); TextIO.put("? "); line = TextIO.getln().trim(); if (line.length() == 0) break; try { N = new BigInteger(line); if (N.signum() == 1) printThreeNSequence(N); else TextIO.putln("Error: The starting value cannot be less than or equal to zero."); } catch (NumberFormatException e) { TextIO.putln("Error: \"" + line + "\" is not a legal integer."); } }

The Solution

/* This program prints out 3N+1 sequences for starting values of N that are entered by the user. Since integers are represented as objects of type BigInteger, it will work for arbitrarily large integers. The starting value specified by the user must be greater than zero. The program continues to read input from the user and print 3N+1 sequences until the user inputs an empty line. If the user's input is illegal, the program will print an error message and continue. */ import java.math.BigInteger; public class BigThreeN { static final BigInteger THREE = new BigInteger("3"); static final BigInteger ONE = new BigInteger("1"); static final BigInteger TWO = new BigInteger("2"); public static void main(String[] args) { String line; // A line of input from the user. BigInteger N; // The starting point for the 3N+1 sequence, // as specified by the user. TextIO.putln("This program will print 3N+1 sequences for positive starting values"); TextIO.putln("that you enter. There is no pre-set limit on the number of"); TextIO.putln("digits in the numbers that you enter. The program will end when"); TextIO.putln("you enter an empty line."); while (true) { TextIO.putln(); TextIO.putln("Enter the starting value, or press return to end."); TextIO.put("? "); line = TextIO.getln().trim(); if (line.length() == 0) break; try { N = new BigInteger(line); if (N.signum() == 1) printThreeNSequence(N); else TextIO.putln("Error: The starting value cannot be less than or equal to zero."); } catch (NumberFormatException e) { TextIO.putln("Error: \"" + line + "\" is not a legal integer."); } } TextIO.putln(); TextIO.putln("OK. Bye for now!"); } // end main() static void printThreeNSequence(BigInteger N) { // Print the 3N+1 sequence starting from N, and count the number // of terms in the sequence. It is assumed that N is not null and // that it is greater than zero. int count; // The number of terms in the sequence. TextIO.putln(); TextIO.putln("The 3N+1 sequence starting with " + N + " is:"); TextIO.putln(); TextIO.putln(N.toString()); // Print N as the first term of the sequence count = 1; while ( ! N.equals(ONE) ){ // Compute and print the next term if (N.testBit(0) == false) { // N is even. Divide N by 2. N = N.divide(TWO); } else { // N is odd. Multiply N by 3, then add 1. N = N.multiply(THREE); N = N.add(ONE); } TextIO.putln(N.toString()); count++; } TextIO.putln(); TextIO.putln("There were " + count + " terms in the sequence."); } // end printThreeNSequence } // end BigThreeN

[ Exercises | Chapter Index | Main Index ]