2

I have a Java program that reads data from a database, and shows it on a user interface. One of these data types is a money amount - and so it automatically triggers me to use BigDecimal as explained here . However in my case I don't do anything with this field except

  1. render it on the UI.
  2. give it another application (over http) who may write it into another database.

Considering the data in the database is of a type similar to double, I don't see any advantage into casting that double precision database field into a BigDecimal because it just gets converted to a string anyway (either for the UI, or for the webservice).

Am I missing something?

Karol Dowbecki
  • 43,645
  • 9
  • 78
  • 111
user1884155
  • 3,616
  • 4
  • 55
  • 108
  • 1
    Doubles can't *store* large amounts of money with sufficient precision. Imagine storing several trillion currency units with ~14 s.f. – meowgoesthedog Mar 12 '18 at 16:13
  • **it just gets converted to a string anyway** - not quite. If you use an ordinary `double` it *could* be rendered as `2.0e3` or perhaps `2.33333333334`. With `BigDecimal` it will be consistent. – OldCurmudgeon Mar 12 '18 at 16:14
  • 2
    If you're actually already storing money as double precision, then you have bigger problems to worry about. – Radiodef Mar 12 '18 at 16:18
  • 1
    "n the database is of a type similar to double" - what do you consider "similar to double"? what type is it in the database, exactly? And what sort of database is it? – Erwin Bolwidt Mar 12 '18 at 16:21
  • *2. give it another application (over http) who may write it into another database* - What happens if this application will need to process the number and make some calculations with it? Are you sure you want to pass it an imprecise value? Your software could still be the cause of precision loss for third-parties which may use the data for different jobs than "just displaying" (and even if you are just displaying you want data to be precise). – BackSlash Mar 12 '18 at 16:28
  • Backslash, Is there any difference between getting the value as double, converting it to String, and then sending it to another application versus getting the value as BigDecimal, and converting that to String before sending? – user1884155 Mar 12 '18 at 16:50
  • @ErwinBolwidt It's of type REAL in a Sybase database – user1884155 Mar 12 '18 at 16:53
  • There is potentially a very damaging difference between using `double` and using `BigDecimal`. The latter will give you exactly the number you initialized the instance with, with infinite precision. The former will not do so in all cases. So with `double` you might not be passing the value you believe you are. – Lew Bloch Mar 12 '18 at 20:54
  • @Lew Bloch is that also the cause if the source of what created the double is itself the same flawed representation (in this case a real type in the database). It seems like the same 64 bits would just be copied without damaging anything – user1884155 Mar 12 '18 at 23:24
  • @user1884155 If you use floating-point numbers you have to deal with the inaccuracies. Your question was about `double` vs. `BigDecimal` to store monetary amounts. The rough SQL equivalents are `REAL` and `DECIMAL`. Floating-point numbers suck at representing money for most purposes. – Lew Bloch Mar 29 '18 at 20:58

1 Answers1

3

There is no requirement to use BigDecimal for monetary values however you must ensure that the amount is stored precisely without any rounding or precision problems normally encountered in float or double data types.

There are few ways to achieve this:

  1. Java 9 comes with JSR 354: Money and Currency API classes e.g. MonetaryAmount.
  2. Store the amount as long using the smallest meaningful currency unit e.g. for USD it's the cent. Look out because some currencies don't use fractional units e.g. YEN.
  3. Mentioned BigDecimal.
  4. Store the amount as String if it doesn't require any processing on your side. It's an ugly approach but if you are only passing the amounts around it might do e.g. read from XML and expose using REST API.
Karol Dowbecki
  • 43,645
  • 9
  • 78
  • 111
  • Is there any difference in: read value from db into string versus read value into BigDecimal, and then convert that to string. – user1884155 Mar 12 '18 at 17:33
  • 1
    @user1884155 under the hood the data is read using [JDBC types](https://docs.oracle.com/javase/8/docs/api/java/sql/JDBCType.html). How are they read and mapped it's up to your code but generally redundant and not-needed transformations like `String` -> `BigDecimal` -> `String` might cause an unforeseen problem e.g. `BigDecimal.toString()` might output [scientific notation when needed](https://docs.oracle.com/javase/8/docs/api/java/math/BigDecimal.html#toString--). It's probably best to write a unit test. – Karol Dowbecki Mar 12 '18 at 18:15