We help IT Professionals succeed at work.

Multiplication accurary

infinidem
infinidem used Ask the Experts™
on
Hi,

working on a simple problem and wanted to get some ideas of the best way around it.  Essentially I want to solve the following problem:

$0.75 * 120%

The answer is $0.90.

I have tried the following:

		BigDecimal bd1 = new BigDecimal(.75);
		BigDecimal bd2 = new BigDecimal(.2);
		BigDecimal bd3 = new BigDecimal(1);
		
		System.out.println( bd1.multiply(bd2.add(bd3)));
		
		System.out.println( 0.75 * ( 1 + 0.20) );

		System.out.println( .75d *  1.2d );
		
		System.out.println( .75d / 5d * 6d);
		
		System.out.println( 75d * 1.2d /100d);
		
		System.out.println( .75d * (( 1d + 0.2d) * 100d)/100d );

Open in new window


With the following output:

0.90000000000000000832667268468867405317723751068115234375
0.8999999999999999
0.8999999999999999
0.8999999999999999
0.9
0.9

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Awarded 2011
Awarded 2011

Commented:

Look at this recent question with solution:

http://www.experts-exchange.com/Programming/Languages/Java/Q_27240925.html?sfQueryTermInfo=1+10+30+bigdecim+yan

  BigDecimal federalTaxableEarnings =  new BigDecimal(40.0276);
 federalTaxableEarnings = federalTaxableEarnings.setScale(2, RoundingMode.HALF_UP);
        System.out.println("earning: " + federalTaxableEarnings);

Open in new window

Awarded 2011
Awarded 2011

Commented:
I think it should be like that for your code:

BigDecimal bd4 = bd1.multiply(bd2.add(bd3));
bd4 = bd4.setScale(2,RoundingMode.HALF_UP);
 System.out.println("bd4: " + bd4);

Let me test.
Awarded 2011
Awarded 2011

Commented:

Yes, this worked for me:
BigDecimal bd1 = new BigDecimal(.75);
		BigDecimal bd2 = new BigDecimal(.2);
		BigDecimal bd3 = new BigDecimal(1);

		
        BigDecimal bd4 = bd1.multiply(bd2.add(bd3));
        bd4 = bd4.setScale(2,RoundingMode.HALF_UP);
         System.out.println("bd4: " + bd4);
         

Open in new window


Output:
bd4: 0.90

Open in new window

The output looks fine to me - floating point operations in any language have a non-infinite amount of precision, and this is something you have to always be aware of.

http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems
Top Expert 2016
Commented:
The reason you have inaccuracy with BigDecimal is that you're using the wrong ctor: if you don't use String ctors with BigDecimal, you're basically starting with inaccuracy (i.e. from floating point, with limited precision). Use the below and you'll find your first printout is spot on
BigDecimal bd1 = new BigDecimal("0.75");
	BigDecimal bd2 = new BigDecimal("0.2");
	BigDecimal bd3 = new BigDecimal("1");

Open in new window

Author

Commented:
The answer is given to two parts as the explanation that a decimal can not be accurately represented via binary and that the constructors for BidDecimal should be with more accuracy.  Thanks Everyone.