Programming 3. Exact Computation of Double Values
Your project in essence is to multiply a floating point value by 3. It may sound simple from the outset.
However, your experience with double
or float
data types may have revealed some challenges.
For instance, you may have noticed that double values are often not exact and computations involve double variables and literals can have errors. Numerous examples are discussed in class about this. For this project, let’s first examine the following code snippet:
System.out.println(3*17.59);
System.out.println(3*56.7);
System.out.println(3*56.7);
System.out.println(3*7.65);
System.out.println(3*75.24);
System.out.println(3*68.95);
System.out.println(3*57.8);
System.out.println(3*17.31);
If the computation involving double values were exact in Java, we would expect the following output,
57.77
170.1
22.95
225.72
206.85
173.4
51.93
Instead, we actually observe the following output,
52.769999999999996
170.10000000000002
22.950000000000003
225.71999999999997
206.85000000000002
173.39999999999998
51.92999999999999
Although there are numerous solutions to print the exact answers that we would expect, this project
is to design a program using String
methods and while
loops to compute these expressions
accurately, i.e., to triple a floating point value (i.e., to multiply it by three)
The essential algorithm (Algorithm 1) to do the exact computation of tripling a floating value by 3 is as follows:
Algorithm 1
- Instead of using
double
orfloat
, represent a float point value as a String throughout. - Given a String
, like
“123.456”`, split the String into two Strings, the whole number part and the fraction part. - Convert the whole number part to an integer, and multiply it by 3. To ease the discussion, let’s denote the result as
tripleWholeNumber
- Convert the fraction number part to an integer, and multiply it by 3 – because we may have to deal with
carrying overs cannot ignore 0’s at the most significant digit, we have to come out a different way to do the multiplication. Regardless, denote the result astripleFraction
. It is important to note that the result may have a carrying over digit, e.g.,456 * 3
yields1368
where1
in1368
is the carrying over digit. We separate the carrying over from the rest, denote the both astripleFractionCarryingOver
andnewtripleFraction
. - The result is also a floating point value whose whole number part shall be
tripleWholeNumber + tripleFractionCarryingOver
and whose fraction part will betripleFractionFraction
. DenotetripleWholeNumber + tripleFractionCarryingOver
asnewTripleWholeNumber
. - The final result should be a String that is the concatenation of
newTripleWholeNumber + "." + newtripleFraction
This project is to develop a robust program based on the algorithm – it should not crash regardless what inputs the user enters and allows the user to do the exact computation repeatedly for different inputs. It can be a challenge to complete this project as it may result in the longest and most complex program you are designing, implementing, and testing thus far. Considering this, we are to divide the project into several programming exercises. By completing Exercises 3.1 – 3.4, you will have the necessary building blocks to complete this project. In Subprojects 1 and 2, you are to complete the required programs. Difference between Subprojects 1 and 2 are, for the former, you are required to print out debug messages while the latter you remove them.
Exercise 3.1 Checking the Sign of the User Input
You shall create a CheckingSign
class. The program prompts the user to enter a floating
point value, checks if it begins with the positive sign ‘+’, or the negative sign ‘-‘, or no sign
at all, and prints out the result on the standard output. It must be stressed that leading white
spaces, trailing white spaces, and white spaces after the sign are allowed in the input; however,
only one value is allowed on a line in the input. The following are example runs of the program
that further exhibit the requirements:
$ java CheckingSign
Enter floating point value:
DEBUG: the user input is < >
DEBUG: the trimed input is <>
Encountered blank input.
$ java CheckingSign
Enter floating point value: + 123
DEBUG: the user input is < + 123 >
DEBUG: the trimed input is <+ 123>
The sign of the input is 1
$ java CheckingSign
Enter floating point value: + 123
DEBUG: the user input is < + 123 >
DEBUG: the trimed input is <+ 123>
The sign of the input is 1
$ java CheckingSign
Enter floating point value: - 123
DEBUG: the user input is < - 123 >
DEBUG: the trimed input is <- 123>
The sign of the input is -1
Note that in the above examples, the program prints out lines beginning from “DEBUG:” for debug purpose. In those lines, we can check values of variables.
Exercise 3.2 Checking Validity of User Input
You shall create a ValidatingDoubleInput
class. The program prompts the user to enter a floating
point value and check if it is a valid input by checking if it is one of the following formats:
- the input can begin with one or more while spaces,
- after that, the input can be 0 or more digits,
- then, the input can have the decimal point,
- after the decimal point, the input can have 0 or more digits, and
- finally, the input can have 0 or more trailing while spaces.
The program should meet the following design constraints:
- the program should read the input as a
String
, - it determines whether the
String
is a valid a floating point value as described, - it displays a message on the standard output indicating if the input is valid.
It must be stressed that the user is only allowed to enter a single value on a line, and multiple values on a single line are considered an invalid input. The following are several runs of the program that exhibit the requirements.
$ java ValidatingDoubleInput
Enter a float point value:
DEBUG: the user input is <>
DEBUG: the trimmed input is <>
Encountered blank input.
$ java ValidatingDoubleInput
Enter a float point value:
DEBUG: the user input is < >
DEBUG: the trimmed input is <>
Encountered blank input.
$ java ValidatingDoubleInput
Enter a float point value: 123
DEBUG: the user input is < 123 >
DEBUG: the trimmed input is <123>
DEBUG: the index of the decimal point is <-1>
DEBUG: the whole number part of the input is <123>
DEBUG: char at index <0> of the whole number part = <1>
DEBUG: char at index <1> of the whole number part = <2>
DEBUG: char at index <2> of the whole number part = <3>
DEBUG: the validity of the whole number part is <true>
DEBUG: the fraction part of the input is <0>
DEBUG: char at index <0> of the fraction part = <0>
DEBUG: the validity of the fraction part is <true>
The input < 123 > is a valid double value of <123>.<0>
$ java ValidatingDoubleInput
Enter a float point value: .123
DEBUG: the user input is < .123 >
DEBUG: the trimmed input is <.123>
DEBUG: the index of the decimal point is <0>
DEBUG: the whole number part of the input is <0>
DEBUG: char at index <0> of the whole number part = <0>
DEBUG: the validity of the whole number part is <true>
DEBUG: the fraction part of the input is <123>
DEBUG: char at index <0> of the fraction part = <1>
DEBUG: char at index <1> of the fraction part = <2>
DEBUG: char at index <2> of the fraction part = <3>
DEBUG: the validity of the fraction part is <true>
The input < .123 > is a valid double value of <0>.<123>
$ java ValidatingDoubleInput
Enter a float point value: 123.456
DEBUG: the user input is < 123.456 >
DEBUG: the trimmed input is <123.456>
DEBUG: the index of the decimal point is <3>
DEBUG: the whole number part of the input is <123>
DEBUG: char at index <0> of the whole number part = <1>
DEBUG: char at index <1> of the whole number part = <2>
DEBUG: char at index <2> of the whole number part = <3>
DEBUG: the validity of the whole number part is <true>
DEBUG: the fraction part of the input is <456>
DEBUG: char at index <0> of the fraction part = <4>
DEBUG: char at index <1> of the fraction part = <5>
DEBUG: char at index <2> of the fraction part = <6>
DEBUG: the validity of the fraction part is <true>
The input < 123.456 > is a valid double value of <123>.<456>
$ java ValidatingDoubleInput
Enter a float point value: 123.1b
DEBUG: the user input is < 123.1b>
DEBUG: the trimmed input is <123.1b>
DEBUG: the index of the decimal point is <3>
DEBUG: the whole number part of the input is <123>
DEBUG: char at index <0> of the whole number part = <1>
DEBUG: char at index <1> of the whole number part = <2>
DEBUG: char at index <2> of the whole number part = <3>
DEBUG: the validity of the whole number part is <true>
DEBUG: the fraction part of the input is <1b>
DEBUG: char at index <0> of the fraction part = <1>
DEBUG: char at index <1> of the fraction part = <b>
DEBUG: the validity of the fraction part is <false>
The input < 123.1b> is an invalid double value
Exercise 3.3 Checking on Carrying-Over
In this exercise, you are to write a TripleInteger
class. The program takes an integer as the input,
multiples it by 3
, and determine whether the computation leads to a carrying over. For instance, if the
integer is 123
, 3*123
is 369
; and if the integer is 421
, 3*431
is 1293
. The former case there
is no carrying over because the result remains a three digit integer while the latter has because it becomes
a 4 digit integer and the carrying over digit is 1
.
The following are several runs of the program that exhibit additional requirements, such as, input/output formatting.
$ java TripleInteger
Enter an integer: 123
3 * 123 is 369 without a carrying over
$ java TripleInteger
Enter an integer: 456
3 * 456 is 1368 with a carrying over of 1
$ java TripleInteger
Enter an integer: 999
3 * 999 is 2997 with a carrying over of 2
Exercise 3.4 Checking Validity of Multiple Inputs of Floating Point Values
This exercise is an extension to Exercise 3.2. In this exercise, you will repeatedly ask the user to
enter floating point value, and display the validity of the input as Exercise 3.2 does. This program
requires you to use nested while
loops. You should name the program ValidatingMultipleDoubleInputs
where the outer while
loop will repeatedly ask the user for a line of input and use another
while
loop to check the input’s validity as a floating point value. The program should exit
from the outer loop if the user enters exit
. The following are several test runs of the programs:
$ java ValidatingMultipleDoubleInputs
Enter a float point value: exit
DEBUG: the user input is <exit>
$ java ValidatingMultipleDoubleInputs
Enter a float point value: eXit
DEBUG: the user input is <eXit>
$ java ValidatingMultipleDoubleInputs
Enter a float point value: exIt
DEBUG: the user input is <exIt>
$ java ValidatingMultipleDoubleInputs
Enter a float point value: EXIT
DEBUG: the user input is <EXIT>
$ java ValidatingMultipleDoubleInputs
Enter a float point value: 123
DEBUG: the user input is < 123>
DEBUG: the trimmed input is <123>
DEBUG: the index of the decimal point is <-1>
DEBUG: the whole number part of the input is <123>
DEBUG: char at index <0> of the whole number part = <1>
DEBUG: char at index <1> of the whole number part = <2>
DEBUG: char at index <2> of the whole number part = <3>
DEBUG: the validity of the whole number part is <true>
DEBUG: the fraction part of the input is <0>
DEBUG: char at index <0> of the fraction part = <0>
DEBUG: the validity of the fraction part is <true>
The input < 123> is a valid double value of <123>.<0>
Enter a float point value: 123.456
DEBUG: the user input is <123.456>
DEBUG: the trimmed input is <123.456>
DEBUG: the index of the decimal point is <3>
DEBUG: the whole number part of the input is <123>
DEBUG: char at index <0> of the whole number part = <1>
DEBUG: char at index <1> of the whole number part = <2>
DEBUG: char at index <2> of the whole number part = <3>
DEBUG: the validity of the whole number part is <true>
DEBUG: the fraction part of the input is <456>
DEBUG: char at index <0> of the fraction part = <4>
DEBUG: char at index <1> of the fraction part = <5>
DEBUG: char at index <2> of the fraction part = <6>
DEBUG: the validity of the fraction part is <true>
The input <123.456> is a valid double value of <123>.<456>
Enter a float point value: 1b.1a
DEBUG: the user input is <1b.1a>
DEBUG: the trimmed input is <1b.1a>
DEBUG: the index of the decimal point is <2>
DEBUG: the whole number part of the input is <1b>
DEBUG: char at index <0> of the whole number part = <1>
DEBUG: char at index <1> of the whole number part = <b>
DEBUG: the validity of the whole number part is <false>
DEBUG: the fraction part of the input is <1a>
DEBUG: char at index <0> of the fraction part = <1>
DEBUG: char at index <1> of the fraction part = <a>
DEBUG: the validity of the fraction part is <false>
The input <1b.1a> is an invalid double value
Enter a float point value: exit
DEBUG: the user input is <exit>
Subproject 1. Exact Computation of Triple Float with Debugging Output
This project is the cumulation of Exercises 3.1 to 3.4. As we discussed at the beginning,
floating point values in Java are often not exact, and their computations can have errors. In this
project, you are to design a program to do an exact “floating value computation”, i.e., to
triple a floating point value or in another word to multiple a floating point value by 3
.
If you have completed Exercises 3.1 to 3.4, you are in a good position to complete this rather challenging project. Because this project is still challenging despite that you completed the preceding exercises, a method that helps you overcome the challenge is to use the debugging techniques. As a result, in this subproject, you are required to print out debugging messages.
Let’s call this program `ExactTripleFloatWithDebugMsg’. The program shall repeatedly
- prompt the user to enter a floating point value a line on the standard input,
- read the input from the standard input,
- split the input into the whole number part and the fraction part,
- multiple each part by 3,
- add the two results together, and
- display the final result.
Additionally, your program should check whether the input is valid – In this project, we only let the program accept floating point numbers that can have at most 5 digits after the decimal point and consider any input that have more than 5 digits after the decimal point as invalid.
The following are several test runs of the program:
$ java ExactTripleFloatWithDebugMsg
Enter a float point value: + 123
DEBUG: the user input is < + 123>
DEBUG: the trimmed input is <+ 123>
DEBUG: the sign of the input is <1>
DEBUG: the index of the decimal point is <-1>
DEBUG: the whole number part of the input is <123>
DEBUG: char at index <0> of the whole number part = <1>
DEBUG: char at index <1> of the whole number part = <2>
DEBUG: char at index <2> of the whole number part = <3>
DEBUG: the validity of the whole number part is <true>
DEBUG: the fraction part of the input is <0>
DEBUG: char at index <0> of the fraction part = <0>
DEBUG: the validity of the fraction part is <true>
DEBUG: the input < + 123> is a valid double value of <1> <123>.<0>
DEBUG: 3 * 0 is 0 without a carrying over
DEBUG: triple whole number plus triple fraction carry over is <369>
The result is +369.0
Enter a float point value: exit
DEBUG: the user input is <exit>
$ java ExactTripleFloatWithDebugMsg
Enter a float point value: - 123.456
DEBUG: the user input is < - 123.456 >
DEBUG: the trimmed input is <- 123.456>
DEBUG: the sign of the input is <-1>
DEBUG: the index of the decimal point is <3>
DEBUG: the whole number part of the input is <123>
DEBUG: char at index <0> of the whole number part = <1>
DEBUG: char at index <1> of the whole number part = <2>
DEBUG: char at index <2> of the whole number part = <3>
DEBUG: the validity of the whole number part is <true>
DEBUG: the fraction part of the input is <456>
DEBUG: char at index <0> of the fraction part = <4>
DEBUG: char at index <1> of the fraction part = <5>
DEBUG: char at index <2> of the fraction part = <6>
DEBUG: the validity of the fraction part is <true>
DEBUG: the input < - 123.456 > is a valid double value of <-1> <123>.<456>
DEBUG: 3 * <456> is 368 with a carrying over of 1
DEBUG: triple whole number plus triple fraction carry over is <370>
The result is -370.368
Enter a float point value: exit
DEBUG: the user input is <exit>
$ java ExactTripleFloatWithDebugMsg.java
Enter a float point value: .456
DEBUG: the user input is < .456 >
DEBUG: the trimmed input is <.456>
DEBUG: the sign of the input is <1>
DEBUG: the index of the decimal point is <0>
DEBUG: the whole number part of the input is <0>
DEBUG: char at index <0> of the whole number part = <0>
DEBUG: the validity of the whole number part is <true>
DEBUG: the fraction part of the input is <456>
DEBUG: char at index <0> of the fraction part = <4>
DEBUG: char at index <1> of the fraction part = <5>
DEBUG: char at index <2> of the fraction part = <6>
DEBUG: the validity of the fraction part is <true>
DEBUG: the input < .456 > is a valid double value of <1> <0>.<456>
DEBUG: 3 * <456> is 368 with a carrying over of 1
DEBUG: triple whole number plus triple fraction carry over is <1>
The result is +1.368
Enter a float point value: exit
DEBUG: the user input is <exit>
$ java ExactTripleFloatWithDebugMsg.java
Enter a float point value: 456.00093
DEBUG: the user input is <456.00093>
DEBUG: the trimmed input is <456.00093>
DEBUG: the sign of the input is <1>
DEBUG: the index of the decimal point is <3>
DEBUG: the whole number part of the input is <456>
DEBUG: char at index <0> of the whole number part = <4>
DEBUG: char at index <1> of the whole number part = <5>
DEBUG: char at index <2> of the whole number part = <6>
DEBUG: the validity of the whole number part is <true>
DEBUG: the fraction part of the input is <00093>
DEBUG: char at index <0> of the fraction part = <0>
DEBUG: char at index <1> of the fraction part = <0>
DEBUG: char at index <2> of the fraction part = <0>
DEBUG: char at index <3> of the fraction part = <9>
DEBUG: char at index <4> of the fraction part = <3>
DEBUG: the validity of the fraction part is <true>
DEBUG: the input <456.00093> is a valid double value of <1> <456>.<00093>
DEBUG: 3 * 00093 is 00279 without a carrying over
DEBUG: triple whole number plus triple fraction carry over is <1368>
The result is +1368.00279
Enter a float point value: exit
DEBUG: the user input is <exit>
$ java ExactTripleFloatWithDebugMsg.java
Enter a float point value: 123.456b
DEBUG: the user input is < 123.456b>
DEBUG: the trimmed input is <123.456b>
DEBUG: the sign of the input is <1>
DEBUG: the index of the decimal point is <3>
DEBUG: the whole number part of the input is <123>
DEBUG: char at index <0> of the whole number part = <1>
DEBUG: char at index <1> of the whole number part = <2>
DEBUG: char at index <2> of the whole number part = <3>
DEBUG: the validity of the whole number part is <true>
DEBUG: the fraction part of the input is <456b>
DEBUG: char at index <0> of the fraction part = <4>
DEBUG: char at index <1> of the fraction part = <5>
DEBUG: char at index <2> of the fraction part = <6>
DEBUG: char at index <3> of the fraction part = <b>
DEBUG: the validity of the fraction part is <false>
The input < 123.456b> is an invalid double value
Enter a float point value: 123.456
DEBUG: the user input is <123.456>
DEBUG: the trimmed input is <123.456>
DEBUG: the sign of the input is <1>
DEBUG: the index of the decimal point is <3>
DEBUG: the whole number part of the input is <123>
DEBUG: char at index <0> of the whole number part = <1>
DEBUG: char at index <1> of the whole number part = <2>
DEBUG: char at index <2> of the whole number part = <3>
DEBUG: the validity of the whole number part is <true>
DEBUG: the fraction part of the input is <456>
DEBUG: char at index <0> of the fraction part = <4>
DEBUG: char at index <1> of the fraction part = <5>
DEBUG: char at index <2> of the fraction part = <6>
DEBUG: the validity of the fraction part is <true>
DEBUG: the input <123.456> is a valid double value of <1> <123>.<456>
DEBUG: 3 * <456> is 368 with a carrying over of 1
DEBUG: triple whole number plus triple fraction carry over is <370>
The result is +370.368
Enter a float point value: exit
DEBUG: the user input is <exit>
Subproject 2. Exact Computation of Triple Float without Debugging Output
The requirement of this subproject is identical to subproject 1 except that you need to remove the debug messages. As such, this subproject can be very simple, just rename your class to `ExtractTripleFloat’ and comment out all statements that print out the debug messages.
It is also important to note by printing out the debug message specified in Subproject 1, you are also restricted to implement the program in the way dictated by the required debug messages. By removing the debugging messages, you gain the freedom to explore different design and implantation strategies. Although not required, you are encouraged to explore different designs and implantation strategies.
You must ensure that the program produces an output that conforms to the example runs below:
$ java ExactTripleFloat
Enter a float point value: 123.456
The result is +370.368
Enter a float point value: 123.456
The result is +370.368
Enter a float point value: + 123.456
The result is +370.368
Enter a float point value: 456.003
The result is +1368.009
Enter a float point value: exit
$ java ExactTripleFloat
Enter a float point value: 987.00943
The result is +2961.02829
Enter a float point value: 987.0012b
The input <987.0012b> is an invalid double value
Enter a float point value: 087.00126
The result is +261.00378
Enter a float point value: exit
Implementation Consideration
You can only use while
loops, String
and Character
methods. You are not allowed to use
System.out.printf
, NumberFormat
, String.format(...)
, BigDecimal
, and any Exception
classes (all of which are not discussed
in class yet.)
The format must be exact; otherwise, CodeLab will reject the output.
Submission
Submit your work on https://codelab.turingscrat.com. Look for “Project 3” under “Programming Projects”.
Submission Deadline
The deadline is posted on the class Website.