2

I'm using BigDecimal to deal with positive numbers in my app, and I want to make it truncate decimals after the 4th one. I seem to almost find what I wanted with RoundingMode.DOWN, but there's some issue when the BigDecimal is created from a double.

For example:

System.out.println("123.11119 = " + new BigDecimal("123.11119").setScale(4, RoundingMode.DOWN)); //Print 123.1111 which is exactly what I want
System.out.println("123.1111 = " + new BigDecimal("123.1111").setScale(4, RoundingMode.DOWN)); //So does this one

HOWEVER, the following prints 123.1110 which is NOT what I want at all:

System.out.println("123.1111 = " + new BigDecimal(123.1111d).setScale(4, RoundingMode.DOWN)); 
0x56794E
  • 20,883
  • 13
  • 42
  • 58
  • 5
    The problem is that `123.1111d` may be stored as `123.111099999999`, thus getting your problem. – Luiggi Mendoza Feb 10 '14 at 21:02
  • Yes. That's what I suspect. Is there a way to get around this? – 0x56794E Feb 10 '14 at 21:02
  • 3
    Yeah. Don't create BigDecimals from doubles. – Dawood ibn Kareem Feb 10 '14 at 21:04
  • 1
    http://rayfd.me/2007/04/26/the-evil-bigdecimal-constructor/ – MariuszS Feb 10 '14 at 21:04
  • If you really must convert a double to a BigDecimal, go via String. Like `new BigDecimal(Double.toString(123.1111))` – Dawood ibn Kareem Feb 10 '14 at 21:08
  • 1
    @DavidWallace Why? The original double is still inaccurate. – user207421 Feb 10 '14 at 21:12
  • 1
    Because converting it to a String has the right smarts to pick the number with the least number of decimal places that's within the range that would get rounded to that double. That means that it will pick the value that you actually want. For example, `Double.toString(123.1111)` will give you `"123.1111"`. This is the only reasonable thing to do when your value is _already_ a double. Naturally, you should avoid having decimal numbers stored as doubles to start with, but if the data is coming from some source that's outside your control, you don't always have a choice. – Dawood ibn Kareem Feb 10 '14 at 21:24

1 Answers1

5

This is because of representation problem.

The value 123.1111d in reality can be something like 123.111091231918498.

That why it is recommended to use string constructor when you want to have exact values.