Opinions on reliability/viability of doing something like this to workaround IEEE oddities in addition and subtraction etc...? I want to avoid BigDecimal,Formatters,etc... GC overhead

exploring this idea.

int fivePlaces = 100000;
Assert.assertEquals(1.13269, add(1.13270, -0.00001, fivePlaces), 0);

private double add(double aPrice,
                   double aModifier,
                   double aPrecision) {
    long price = (long) (aPrice * aPrecision);
    long modifier= (long) (aModifier * aPrecision);
    long adjustedPrice = price + modifier;
    return adjustedPrice / aPrecision;

for example:

    double d = 1.30784;
    double d2 = -0.00005;
    double d3 = d + d2;
    double d4 = add(d, d2, 100000);

the idea is to avoid this result: 1.3077899999999998

and get this one: 1.30778

with primitives.

  • 1
    What exactly are you trying to achieve with this code? If you clarify that, you might gather some factual explanations instead of mere opinions. – njuffa Sep 22 '16 at 19:30
  • Opinions on code that is already written (and works) should go here --> CodeReview.SE. As for my personal opinion - this code screams "I don't understand how doubles work!!!" at me. – Ordous Sep 22 '16 at 19:41
  • updated with clarification of intent. – andmer Sep 22 '16 at 19:50
  • 2
    You want to avoid an efficient, precise implementation that was built for purposes such as yours (BigDecimal) because of premature optimization (GC). Your program needs to be correct first, then you profile to find areas that can benefit from optimization only if needed. – user22815 Sep 22 '16 at 20:05
  • 1
    @andmer Modern GCs don't suffer much from that churn due to optimizations they make. Perhaps if performance is too slow, just use int or long as a "count of cents"? If you do not need arbitrary-precision and length, that might work while still guaranteeing precision. – user22815 Sep 22 '16 at 20:51

The number 1.30778 cannot be represented exactly as a double. For this number, the most accurate representation will be 0x3FF4ECAAB8A5CE5B which is 1.30777999999999994251709267701.

The core problem with this is do not use a double to store money. Any use of a floating point number will inherently have problems with monetary amounts.

Suck it up and use a BigDecimal.

See also:

| improve this answer | |
  • Thanks, I understand these things, but was throwing some ideas out working w/o BigDecimal,etc... – andmer Sep 22 '16 at 20:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.