noboru
noboru

Reputation: 21

BigDecimal is losing precision

I'm using BigDecimal, and it lost precision when it print rate and add the rate.

import java.math.MathContext;
import java.math.BigDecimal;
public class Calc
{

    public static void main( String[] args ) {
        MathContext mc = new java.math.MathContext( 3 );

        double r = 1668.00;
        BigDecimal rate =   new BigDecimal( r,mc );
        BigDecimal taxWitholdingRate = new BigDecimal( 0.1185, new MathContext(4) );
        BigDecimal unitFrequency = new BigDecimal( 11.5,mc);

        System.out.println(   rate  );
        System.out.println(   taxWitholdingRate  );
        System.out.println(   unitFrequency  );


        BigDecimal serviceCost2 = new BigDecimal(0,mc);
        serviceCost2 = rate.multiply(taxWitholdingRate, mc  );  
        System.out.println(   serviceCost2  );
        serviceCost2  = serviceCost2.add( rate, mc);                        
        System.out.println(   (BigDecimal)serviceCost2 );
        serviceCost2 = serviceCost2.multiply(unitFrequency );
        System.out.println(   serviceCost2 );
    }    
}

java -cp . Calc
1.67E+3
0.1185
11.5
198
1.87E+3
21505

Upvotes: 1

Views: 3054

Answers (1)

Elliott Frisch
Elliott Frisch

Reputation: 201419

Assuming these are supposed to be currency figures (to the hundredths), I think you wanted to use BigDecimal.setScale(int, RoundingMode) and something like

public static void main(String[] args) {
    BigDecimal rate = new BigDecimal("1668.00");
    BigDecimal taxWitholdingRate = new BigDecimal("0.1185");
    BigDecimal unitFrequency = new BigDecimal("11.5");

    System.out.println(rate);
    System.out.println(taxWitholdingRate);
    System.out.println(unitFrequency);

    BigDecimal serviceCost2 = new BigDecimal("0");
    serviceCost2 = rate.multiply(taxWitholdingRate);
    System.out.println(serviceCost2.setScale(2, RoundingMode.HALF_UP));
    serviceCost2 = serviceCost2.add(rate);
    System.out.println(serviceCost2.setScale(2, RoundingMode.HALF_UP));
    serviceCost2 = serviceCost2.multiply(unitFrequency);
    System.out.println(serviceCost2.setScale(2, RoundingMode.HALF_UP));
}

Output is

1668.00
0.1185
11.5
197.66
1865.66
21455.07

Upvotes: 2

Related Questions