Reputation: 153
In my program i'm posting the payment amount value to controller and i'm converting that value to Integer. Because I need to convert this value to cents before calling web service. I'm using java and convert String to Integer code given below
(int)(Double.parseDouble(httpRequest.getParameter(PAYMENT_AMOUNT).trim()) * 100);
payment.jsp
page look like this
Payment Amount: <input type="text" id="paymentAmount" name="paymentAmount" value="1.00" />
For many input values it gives the correct output.
But for some values like 8.03 as input it return 802 as output value . This happens in 9.03,9.04 ,10.03,10.04,11.03 etc ... what could be the reason for this issue?
Upvotes: 3
Views: 141
Reputation: 331
As a side note, you might want to reconsider using int types to store cent values esp when dealing with large numbers.
To add more to earlier answers on floating-point issues in Java, and the need for BigDecimal, refer to some explanation here:
http://www.drdobbs.com/jvm/javas-floating-point-imprecision/240168744
You can change your code to:
(new BigDecimal(httpRequest.getParameter(PAYMENT_AMOUNT).trim(), MathContext.DECIMAL64)).multiply(new BigDecimal(100, MathContext.DECIMAL64)).intValue()
Another note: I would be cautious about assuming that you will get a String object back in the getParameter() call above esp. if someone is attempting to call your service without passing the PAYMENT_AMOUNT parameter.
Upvotes: 1
Reputation: 533520
You need to round the result. The problem you have is that floating point numbers are almost but not exactly the number it appears when printed as a string. This shows up as a problem when you perform calculations.
I suggest you try
(int) Math.round( Double.parseDouble( httpRequest.getParameter(PAYMENT_AMOUNT).trim()) * 100);
In your specific case, you can see with BigDecimal what the actual representation of a double
is
double d = 8.03;
BigDecimal bd = new BigDecimal(d);
System.out.println("bd: " + bd);
double d100 = d * 100;
System.out.println("d100: " + d100);
int i100 = (int) d100;
System.out.println("i100: " + i100);
int r100 = (int) Math.round(d100);
System.out.println("r100: " + r100);
prints
bd: 8.0299999999999993605115378159098327159881591796875
d100: 802.9999999999999
i100: 802
r100: 803
So you can see the actual value of 8.03
is slightly less than 8.03
which means however that when you * 100
and round down it means that you get 802
not 803
as expected.
The best solution is to round the result which finds the closest representable value.
Upvotes: 2