Floating point values are numbers with decimals. Java uses the type double
to represent floating point values.
(Java also has a float
type; however, it is not featured in the AP CS A Java Subset. Java assumes that decimal literals are of type double
unless explicitly specified as float
.)
Roundoff error example
double total = 0.0;
total += 1.99;
total += 2.49;
total += 0.99;
System.out.println(total);
The code above prints: 5.470000000000001
Mathematically, 1.99 + 2.49 + 0.99
is 5.47
.
This is an example of a roundoff error (also known as a rounding error). Java uses a fixed number of bits to represent the value of a double
. The precision of mathematical calculations is limited by the number of bits used to represent the values involved.
Addressing roundoff error
Beginning programmers often seek to fix roundoff errors. This is not an appropriate approach. Although it is possible to perform floating point operations with arbitrary precision, it is not possible to perform them with inifinite precision.
Roundoff error isn’t fixed. Roundoff error is addressed to ensure that programs work as intended. Approaches to address roundoff error include:
- compare
double
values using a tolerance to account for roundoff error. - avoid roundoff error by using
int
values instead ofdouble
values. - round a result to a specific precision before display it.
Comparing double
values using ==
double total = 0.0;
total += 1.99;
total += 2.49;
total += 0.99;
if(total == 5.47)
System.out.println("total is 5.47");
else
System.out.println("total is not 5.47");
The code above prints: total is not 5.47
As shown in the previous example, the value of total
is 5.470000000000001
. The expression 5.470000000000001 == 5.47
evalutes to false
.
Comparing double
values using ==
or !=
is usually a mistake. In most cases, the programmer isn’t interested in whether two double
values are exactly equal, but rather whether they are close enough.
Comparing double
values using a tolerance
double total = 0.0;
total += 1.99;
total += 2.49;
total += 0.99;
final double TOLERANCE = 0.009;
if(Math.abs(total - 5.47) < TOLERANCE)
System.out.println("total is close enough to 5.47");
else
System.out.println("total is not close enough to 5.47");
The code above prints: total is close enough to 5.47
The code calculates the difference between total
and 5.47
. If the difference is less than the tolerance, the values are considered close enough. The tolerance is specified by the programmer.
The absolute value of the difference is used to prevent all values of total
less than 5.47
from causing the condition to evaluate to true
.
The constant TOLERANCE
is used to make the code easier to understand and modify.
Using int
values instead of double
values
int total = 0;
total += 199;
total += 249;
total += 99;
System.out.println(total);
if(total == 547)
System.out.println("total is 547");
else
System.out.println("total is not 547");
The code above prints:
547
total is 547
This example uses int
values instead of double
values. If the values represented amounts of money, these would represent the amounts in cents instead of in dollars.
Calculations using int
values do not suffer from roundoff error. Calculations with int
values are subjet to overflow, which is a diffeent concern.
Rounding a double
value before output
Rounding to the nearest int
double total = 0.0;
total += 1.99;
total += 2.49;
total += 0.99;
int dollars = (int) (total + 0.5);
System.out.println(dollars);
System.out.println(total);
The code above prints:
5
5.470000000000001
In this example, total
is known to be non-negative (>= 0
). The expression: (int) (total + 0.5)
rounds the non-negative value of total
to the nearest int
.
For negative (< 0
) values of total, the expression (int) (total - 0.5)
rounds the value of total
to the nearest int
.
Note that the value of total remains 5.470000000000001
.
This technique is featured in the AP CS A Course Description.
Rounding with Math.round
double total = 0.0;
total += 1.99;
total += 2.49;
total += 0.99;
int dollars = (int) Math.round(total);
System.out.println(dollars);
System.out.println(total);
The code above prints:
5
5.470000000000001
Math.round
returns a long
. If it is know that the value is within the range of an int
, the value can be cast to an int
. Math.round
works for positive values, negative values, and zero.
Math.round
is outside the scope of the AP CS A Exam.
DecimalFormat
class
DecimalFormat formatter = new DecimalFormat("#.##");
double num = 123.45678;
System.out.println(formatter.format(num));
System.out.println(num);
num = 123.4;
System.out.println(formatter.format(num));
The code above prints:
123.46
123.45678
123.4
A DecimalFormat
object can be constructed with a String
pattern that specifies how double
values should be formatted. The pattern #.##
specifies that the value should be rounded to 2 decimal places.
The format
method returns a String
with the argument formatted as specified earlier.
DecimalFormat
is outside the scope of the AP CS A Exam.
See the DecimalFormat Javadoc for more information.
As currency
double total = 0.0;
total += 1.99;
total += 2.49;
total += 0.99;
NumberFormat dollarsFormatter = NumberFormat.getCurrencyInstance();
System.out.println(dollarsFormatter.format(total));
When run on a computer configured to use US dollars, the code above prints:
$5.47
The Java Library includes the NumberFormat
class. NumberFormat
can be used to quickly format a double
value as currency, including adding a currency specifier and rounding.
NumberFormat
is outside the scope of the AP CS A Exam.
Additional resources
- Data representation using binary includes demonstrations of integer overflow.
Help & comments
Get help from AP CS Tutor Brandon Horn