7

I'm having slight difficulty in performing a calculation in Java. Here is what I'm trying to do -

((0.053800 * (500000/1000)) + 4) * 0.85

In my java application, it returns 26.264999999999997, which if you round up to 2 decimal places, becomes 26.26.

But in MS Excel, the same formula returns 26.265000.. and therefore the rounded result is 26.27.

If my Java application is returning incorrect value, what can I do to correct it?

Silent Walker
  • 330
  • 1
  • 5
  • 11
  • @pst see http://ideone.com/Gk8hR – Bala R Jun 03 '11 at 02:24
  • 1
    The main difference is probably between floating-point arithmetic, and real math (as if done by hand). – motoku Jun 03 '11 at 02:25
  • 1
    Huh? It'll all be done in double-precision as is since floating-point literals without an "f" modifier are required to be `double` by the Java Language Spec, (and except for `500000/1000` which will be integer division (though it won't lose anything since there's no remainder to that quotient)). – QuantumMechanic Jun 03 '11 at 02:29
  • 2
    Why did you round to 2 decimals? If you round to 3, they round to the same result. If you round to 1, they round to the same result. – Atreys Jun 03 '11 at 02:29
  • @QuantumMechanic: According to my Python professor, financial institution's softwares, and financial softwares, have been switching from lossy numerical manipulation. – motoku Jun 03 '11 at 02:35
  • 1
    Actually the Java app is returning the correct value, according to the IEEE 754 standard. Unfortunately, IEEE 754 arithmetic is different from real number arithmetic, and involves rounding operations on the numbers. Use BigDecimal if you want precise calculation of real numbers – ignis Jun 03 '11 at 02:36
  • possible duplicate of [Why does Perl's sprintf not round floating point numbers correctly?](http://stackoverflow.com/questions/1651671/why-does-perls-sprintf-not-round-floating-point-numbers-correctly) – Greg Hewgill Jun 03 '11 at 02:37
  • 1
    @sean, I think QuantumMechanic was replying to pst – ignis Jun 03 '11 at 02:37
  • @Sean: I'm sure they are, but I was just pointing out that the first commenter's suggestion is incorrect, since the calculation already is being done in double precision. – QuantumMechanic Jun 03 '11 at 02:39
  • @ignis, @QuantumMechanic, my misunderstanding. – motoku Jun 03 '11 at 02:41
  • What do you expect from `500 000/1 000`? I would expect it to be 500, and `0.053800 * 500` is't different from `0.0538 * 500` which is `5.38 * 5`. So we're talking about ((5.38 * 5) + 4) * 0.85, just to simplify it a bit. – user unknown Jun 03 '11 at 02:57
  • @Atreys, because that's what the requirement is. – Silent Walker Jun 03 '11 at 03:12

2 Answers2

6

See my answer here for an explanation of what's going on.

Community
  • 1
  • 1
Jim Garrison
  • 85,615
  • 20
  • 155
  • 190
4

The following is a much better approximation, which results in the same value in this case:

import java.math.BigDecimal;
import java.math.MathContext;

public class Test {
    public static void main(String[] args) {
        //double d = ((0.053800 * (500000/1000)) + 4) * 0.85;
        BigDecimal d = ((new BigDecimal(0.053800).multiply(new BigDecimal(500000).divide(new BigDecimal(1000)))).add(new BigDecimal(4))).multiply(new BigDecimal(0.85));
        System.out.println(d.round(MathContext.DECIMAL32));
    }
}
RMorrisey
  • 7,637
  • 9
  • 53
  • 71