2008-10-07 16:59:41 8 Comments

Seems like the subtraction is triggering some kind of issue and the resulting value is wrong.

```
double tempCommission = targetPremium.doubleValue()*rate.doubleValue()/100d;
```

78.75 = 787.5 * 10.0/100d

```
double netToCompany = targetPremium.doubleValue() - tempCommission;
```

708.75 = 787.5 - 78.75

```
double dCommission = request.getPremium().doubleValue() - netToCompany;
```

877.8499999999999 = 1586.6 - 708.75

The resulting expected value would be 877.85.

What should be done to ensure the correct calculation?

### Related Questions

#### Sponsored Content

#### 44 Answered Questions

### [SOLVED] How do I convert a String to an int in Java?

**2011-04-07 18:27:54****Unknown user****5605921**View**2752**Score**44**Answer- Tags: java string int type-conversion

#### 63 Answered Questions

### [SOLVED] Round to at most 2 decimal places (only if necessary)

**2012-08-06 17:17:48****stinkycheeseman****1889413**View**2145**Score**63**Answer- Tags: javascript decimal rounding decimal-point

#### 63 Answered Questions

#### 78 Answered Questions

### [SOLVED] Is Java "pass-by-reference" or "pass-by-value"?

**2008-09-02 20:14:29****user4315****1757748**View**5832**Score**78**Answer- Tags: java methods parameter-passing pass-by-reference pass-by-value

#### 6 Answered Questions

### [SOLVED] How to directly initialize a HashMap (in a literal way)?

**2011-07-23 18:40:33****jens****1071601**View**871**Score**6**Answer- Tags: java dictionary collections initialization

#### 53 Answered Questions

### [SOLVED] Creating a memory leak with Java

**2011-06-24 16:11:52****Mat B.****578970**View**2888**Score**53**Answer- Tags: java memory memory-leaks

#### 35 Answered Questions

### [SOLVED] Fastest way to determine if an integer's square root is an integer

**2008-11-17 13:43:21****Kip****250419**View**1334**Score**35**Answer- Tags: java math optimization perfect-square

## 13 comments

## @Eric Weilnau 2008-10-07 17:09:27

To control the precision of floating point arithmetic, you should use java.math.BigDecimal. Read The need for BigDecimal by John Zukowski for more information.

Given your example, the last line would be as following using BigDecimal.

This results in the following output.

## @Ates Goral 2008-10-07 17:17:49

There's no way you can altogether "avoid" floating point arithmetic errors. The number of bits used in representing a number will always be finite. All you can do is to use data types with higher precision (bits).

## @Eric Weilnau 2008-10-07 17:29:32

That is true. I will edit my answer to more accurately reflect the use of BigDecimal.

## @Joshua Goldberg 2011-07-12 16:05:12

I'll add a note that BigDecimal

divisionneeds to be treated a little bit differently than +,-,* since by default it will throw an exception if it cannot return an exact value (1 / 3, e.g.). In a similar situation I used: BigDecimal.valueOf(a).divide(BigDecimal.valueOf(b), 25, RoundingMode.HALF_UP).doubleValue(), where 25 if the maximal digits of precision (more than needed by the double result).## @Johann Zacharee 2008-10-07 17:20:34

As the previous answers stated, this is a consequence of doing floating point arithmetic.

As a previous poster suggested, When you are doing numeric calculations, use

`java.math.BigDecimal`

.However, there is a gotcha to using

`BigDecimal`

. When you are converting from the double value to a`BigDecimal`

, you have a choice of using a new`BigDecimal(double)`

constructor or the`BigDecimal.valueOf(double)`

static factory method. Use the static factory method.The double constructor converts the entire precision of the

`double`

to a`BigDecimal`

while the static factory effectively converts it to a`String`

, then converts that to a`BigDecimal`

.This becomes relevant when you are running into those subtle rounding errors. A number might display as .585, but internally its value is '0.58499999999999996447286321199499070644378662109375'. If you used the

`BigDecimal`

constructor, you would get the number that is NOT equal to 0.585, while the static method would give you a value equal to 0.585.on my system gives

## @Richard 2011-10-04 08:28:18

I have come across this problem many times and it is really quite annoying!

## @Oleg Khalidov 2015-10-13 13:16:52

days saver. thanx!

## @guitar_freak 2015-12-10 10:31:16

Note, that the reason is, that the static method uses an UNLIMITED MathContext what practically means: new BigDecimal(value, new MathContext(0, RoundingMode.HALF_UP)) ;)

## @dog 2009-04-30 20:42:03

I would modify the example above as follows:

This way you avoid the pitfalls of using string to begin with. Another alternative:

I think these options are better than using doubles. In webapps numbers start out as strings anyways.

## @Doug 2012-04-05 12:50:42

This is a fun issue.

The idea behind Timons reply is you specify an epsilon which represents the smallest precision a legal double can be. If you know in your application that you will never need precision below 0.00000001 then what he suggests is sufficient to get a more precise result very close to the truth. Useful in applications where they know up front their maximum precision (for in instance finance for currency precisions, etc)

However the fundamental problem with trying to round it off is that when you divide by a factor to rescale it you actually introduce another possibility for precision problems. Any manipulation of doubles can introduce imprecision problems with varying frequency. Especially if you're trying to round at a very significant digit (so your operands are < 0) for instance if you run the following with Timons code:

Will result in

`1499999.9999999998`

where the goal here is to round at the units of 500000 (i.e we want 1500000)In fact the only way to be completely sure you've eliminated the imprecision is to go through a BigDecimal to scale off. e.g.

Using a mix of the epsilon strategy and the BigDecimal strategy will give you fine control over your precision. The idea being the epsilon gets you very close and then the BigDecimal will eliminate any imprecision caused by rescaling afterwards. Though using BigDecimal will reduce the expected performance of your application.

It has been pointed out to me that the final step of using BigDecimal to rescale it isn't always necessary for some uses cases when you can determine that there's no input value that the final division can reintroduce an error. Currently I don't know how to properly determine this so if anyone knows how then I'd be delighted to hear about it.

## @Tomasz 2013-04-27 04:53:20

Better yet use JScience as BigDecimal is fairly limited (e.g., no sqrt function)

## @Benj 2015-07-21 09:58:46

Thanks for the lib ! But isn't it a bit overloaded for simple thing ?

## @Tomasz 2015-07-24 00:30:03

@Benj you could say the same about Guava ;)

## @Mike Stratton 2012-03-11 15:07:26

It's quite simple.

Use the %.2f operator for output. Problem solved!

For example:

The above code results in a print output of: 877.85

The %.2f operator defines that only TWO decimal places should be used.

## @Benj 2015-07-21 09:58:09

This does NOT solve mantisse approximation and rounding issues ! What you see isn't what you work on !

## @mortensi 2016-01-05 12:57:48

If you round to 1 decimal, then you'll get 877.8. Which probably is not want you wanted.

## @Timon 2011-11-30 13:35:35

Although you should not use doubles for precise calculations the following trick helped me if you are rounding the results anyway.

Example:

Which prints:

More info: http://en.wikipedia.org/wiki/Double_precision

## @Michael Borgwardt 2011-11-30 13:42:12

Since .5

canbe exactly represented as a binary fraction, the only case where this would have an effect is when the value is legitimately different.## @Timon 2011-11-30 15:06:58

@Michael: my example was flawed. However the problem remains. Therefore I added an example.

## @Michael Borgwardt 2011-11-30 15:14:48

The problem remains that your method will return the wrong result when the value really

issomething like 0.01499999999 - it's just fundamentally the wrong way to address problems like this.## @Denis 2009-10-27 07:45:24

## @Roman Kagan 2009-06-19 14:45:33

So far the most elegant and most efficient way to do that in Java:

## @Steve Klabnik 2008-10-07 17:04:26

Any time you do calculations with doubles, this can happen. This code would give you 877.85:

double answer = Math.round(dCommission * 100000) / 100000.0;

## @Michael Myers 2008-10-07 17:22:00

Better divide that by 100000.0 instead of just 100000; Math.round returns a long, so you'll be using integer division otherwise.

## @toolkit 2008-10-07 17:14:13

Another example:

Use BigDecimal instead.

EDIT:

Also, just to point out this isn't a 'Java' rounding issue. Other languages exhibit similar (though not necessarily consistent) behaviour. Java at least guarantees consistent behaviour in this regard.

## @tloach 2008-10-07 17:09:40

Save the number of cents rather than dollars, and just do the format to dollars when you output it. That way you can use an integer which doesn't suffer from the precision issues.

## @James Schek 2008-10-07 23:45:59

The only catch here is that a fraction of a cent can be lost early in the process--this might be bad for financial apps. If this is a problem, you can save the number of 1/10 cents or whatever precision you need.

## @Trenton 2009-10-27 07:54:36

If I could go back in time and give my past-self one "trick", this would be it. Price as pennies! (or 1e-3 or 1e-6 -- which is still good for 2+ million dollars as an int)

## @Adam Bellaire 2008-10-07 17:02:42

See responses to this question. Essentially what you are seeing is a natural consequence of using floating point arithmetic.

You could pick some arbitrary precision (significant digits of your inputs?) and round your result to it, if you feel comfortable doing that.