programming forums Java Java JSRs Mobile Certification Databases Caching Books Engineering OS Languages Paradigms IDEs Build Tools Frameworks Products This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
Sheriffs:
Saloon Keepers:
Bartenders:

# NumberFormat rounding problem

Andrey Slastenov
Greenhorn
Posts: 4
Dears,

I am in the beginning of Murach Java Programming (5th Edition) book.
There is example of NumberFormat rounding problem on page 108 (half-even algorithm).

But, after I try an example from the book: (InvoiceApp), I didn't find any problem with rounding.

My program code:

expected results, according to the book explanation:

but I am getting:

I am using Java 9 and Netbeans 9.

Some one can explain me, why I didn't get any rounding problem like book mention? Is there rounding algorithm change in NumberFormat class?

Rancher
Posts: 2240
28
rounding problem like book mention

Can you post examples of the rounding problems the book says you should get?

Andrey Slastenov
Greenhorn
Posts: 4
rounding problem like book mention

Can you post examples of the rounding problems the book says you should get?

When you use the format() method of a NumberFormat object, the numbers are automatically rounded using a technique called half-even. This technique rounds up if the preceding digit is odd, but rounds down if the preceding digit is even. U, for example, the currency format is used for a value of 123.455, the formatted result is S 123.46, which is what you would expect. But if the value is 123.445, the result is 123.44. Although this is okay for many applications, it can cause problems in others. You'll learn more about this later in this chapter.

After that on page 108:
How to debug a rounding error
The console at the top of figure 3-1 4 shows more output from the Invoice application in figure 3- 13. Here, the results for a subtotal entry of 100.05 don't add up! If the discount amount is \$10.00, the total before tax should be \$90.05, but it's \$90.04. What's causing this error, and how can we fix it?
To determine the cause, you can add debugging statements like the ones shown here. These statements display the unformatted results before the formatted results. For example, if you look at the unformatted results, yuu can begin to figure out what's causing the problem. To start, the discount amount is 10.005, which isn't a valid monetary amounL For most financial applications, this amount should be rounded up to 10.01. However, because of the way the umberFormat class rounds the numbers, the discount amount value of 10.005 is rounded down lo 10.00. Similarly, the rest of the numbers are not valid monetary amounts either, which could lead to more rounding problems.
Although an error like this may be acceptable in some applications, it is unacceptable in most business applications. And for those applications, you need to provide solutions that deliver the results that you want. Imagine getting an invoice that didn't add up!
One solution is lo add code that rounds the results of each calculation to 2 decimal places. That way, the double types store valid monetary values. Then, you can use the NumberFormat class to format these numbers without worrying about it introducing a rounding error. To implement this solution, you can add statements like the shaded statements shown in the second example. Here, the first shaded statement rounds the discountArnount value to 2 decimal places. Then, the second shaded statement rounds the salesTax value to 2 decimal places. It isn't necessary to round the tota!BeforeTax or total variables since the code uses addition and subtraction to calculate these values. As a result, these calculations shouldn't introduce any new decimal places.
Although this solution is adequate for most applications, it uses the double data type, which is a floating-point number that's only designed to store approximate values. In addition, the roundO method of the Math class doesn't give you much control over how the rounding works. So, if you need to be 100% sure that your decimal numbers are exact, or if you need more control over how those numbers are rounded, it's generally considered a best practice to use the BigDecirnal class as described in the next few figures.

and page 109:

but when I start the code from the example (please check my previous message), I didn't face this problem at all. When I try this code with subtotal value of 100.05 I am getting:

So the problem is - rounding mode working not like explained in the book. I am trying to understand why.

Rancher
Posts: 2240
28
I am getting:

Are those the expected values?  If not please add a comment showing what is expected.  For example:

Discount amount:  \$10.01   <<<<<< This should be \$10.00

Andrey Slastenov
Greenhorn
Posts: 4
I am getting:

Are those the expected values?  If not please add a comment showing what is expected.  For example:

Discount amount:  \$10.01   <<<<<< This should be \$10.00

Expected:

Enter subtotal: 100.05
Discount percent: 10%
Discount amount: \$10.00
Total before tax: \$90.04
sales tax, \$4.50
Invoice total : \$94.55
continue? (y/n):

Real results:

Enter subtotal:   100.05
Discount percent: 10%
Discount amount:  \$10.01  <-- should be 10.00
Total before tax: \$90.05 <--- should be 90.04
Sales tax:        \$4.50
Invoice total:    \$94.55

Rancher
Posts: 2240
28
Ok, thanks.  That is clear now.

Here is a small test program that shows the differences between java 8 and java 7:

Java 8 rounds differently depending on ???
Java 7 always rounded down

Andrey Slastenov
Greenhorn
Posts: 4
• 1
Finally, I found the clear explanation for rounding modes. It looks like, that explanation in the book isn't clear enough.

In the book:

When you use the format() method of a NumberFormat object, the numbers are automatically rounded using a technique called half-even. This technique rounds up if the preceding digit is odd, but rounds down if the preceding digit is even, for example, the currency format is used for a value of 123.455, the formatted result is 123.46, which is what you would expect. But if the value is 123.445, the result is 123.44. Although this is okay for many applications, it can cause problems in others. You'll learn more about this later in this chapter.

In the java documentation:
HALF_EVEN

public static final RoundingMode HALF_EVEN
Rounding mode to round towards the "nearest neighbor" unless both neighbors are equidistant, in which case, round towards the even neighbor. Behaves as for RoundingMode.HALF_UP if the digit to the left of the discarded fraction is odd; behaves as for RoundingMode.HALF_DOWN if it's even. Note that this is the rounding mode that statistically minimizes cumulative error when applied repeatedly over a sequence of calculations. It is sometimes known as "Banker's rounding," and is chiefly used in the USA. This rounding mode is analogous to the rounding policy used for float and double arithmetic in Java.