-3

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);
    System.out.println(d3);
    System.out.println(d4);

the idea is to avoid this result: 1.3077899999999998

and get this one: 1.30778

with primitives.

andmer
  • 9
  • 1
  • 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](http://codereview.stackexchange.com/). 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_. –  Sep 22 '16 at 20:05
  • Yes, exactly. (context Its not premature, this is an optimization phase) BigDecimal is really not efficient, its 10x slower allocates and churns memory/GC like crazy as opposed to primitive counterpart on the stack. – andmer Sep 22 '16 at 20:16
  • 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. –  Sep 22 '16 at 20:51

1 Answers1

5

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:

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