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:

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

Help & comments

Get help from AP CS Tutor Brandon Horn

Comment on Floating point roundoff error