0

I have the following situation, when I give e.g. one number 10.55000, this number is rounded correctly to 10.55, then after adding 10.5501, everything is also fine because I get 21.1001, but in the next stage, when I add the number 10.55 I get the following result: 31.6501000001, and I should receive 31.6501. What should I do to get in stage 3 of 31.6501 instead of 31.6501000001.

This is my Numbers class:

class Numbers {

    private double result;
    private double currentNumber;

    public void calculateResult (double number) {

        currentNumber = number;
        result += currentNumber ;
    }

    public String getResult() {

        DecimalFormat decimalFormat = new DecimalFormat("#.##########");
        decimalFormat.setRoundingMode(RoundingMode.CEILING);

        return decimalFormat.format(result);
    }
}

This is my main method:

    Numbers numbers = new Numbers();

    numbers.calculateResult(10.55000);
    System.out.println(numbers.getResult());

    numbers.calculateResult(10.5501);
    System.out.println(numbers.getResult());

    numbers.calculateResult(10.55);
    System.out.println(numbers.getResult());
UnknownBoy
  • 169
  • 7
  • 7
    You have to decide the scale and precision for your double number. Did you try BigDecimals? – Kris Oct 18 '19 at 08:41
  • Note that 10.55000 is not "rounded" to 10.55 - it's basically the same value with just a different representation (of course `BigDecimal` makes a distinction but from a mathematical point of view both are the same). – Thomas Oct 18 '19 at 08:47
  • Related: [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – MC Emperor Oct 18 '19 at 08:52
  • Thank you, Kris, that solved my problem. – UnknownBoy Oct 18 '19 at 09:18

2 Answers2

1

As already stated floating point numbers such as float and double suffer from precision issues and those can add up with each calculation. For more exact calculations you should use BigDecimal instead.

Here's an example of your class that keeps the same method signatures but uses BigDecimal internally:

class Numbers {
  private BigDecimal result = BigDecimal.ZERO;
  private BigDecimal currentNumber;

  public void calculateResult( double number ) {
    currentNumber = BigDecimal.valueOf( number );
    result = result.add( currentNumber );
  }

  public String getResult() {
    //no rounding here because your question doesn't involve any actual rounding
    return result.toString();
  }
}

Output for your test calculations:

10.55
21.1001
31.6501

Note that the example above doesn't actually do any rounding, i.e. if you add 0.000001 then this will get reflected in the resulting value.

If you need to round to let's say 4 significant decimal places (0 to 4 at most) you could use this instead:

return result.setScale( 4, RoundingMode.CEILING ).stripTrailingZeros().toString();
Thomas
  • 87,414
  • 12
  • 119
  • 157
0

You must set your format appropriately. Use new DecimalFormat("#.####") instead of new DecimalFormat("#.##########") because you only want to see 4 digits after the dot.

This will give you

10,55
21,1001
31,6502

If you need higher precision you need to use a different data type for example BigDecimal

Jannik
  • 1,583
  • 1
  • 14
  • 22
  • This does not solve my problem because it is not a universal mechanism, because if I enter a number e.g. 85.55017, it will cut off the number 7 – UnknownBoy Oct 18 '19 at 08:47
  • "If you need higher precision ..." note that even with less fraction digits there might be precision errors when using floating point numbers. – Thomas Oct 18 '19 at 08:48
  • @UnknownBoy The `7` is not cut off. The value is rounded to `85,5502`. That's the result I would expect from rounding. As mentioned, if you need precise results without rounding you cannot use `double` values as they are inherently imprecise. – Jannik Oct 18 '19 at 08:53