We know that using double for currency is error-prone and not recommended. However, I\'m yet to see a realistic example, where BigDecimal
The following would appear to be a decent implementation of a method that needed to "round down to the nearest penny".
private static double roundDowntoPenny(double d ) {
double e = d * 100;
return ((int)e) / 100.0;
}
However, the output of the following shows that the behavior isn't quite what we expect.
public static void main(String[] args) {
System.out.println(roundDowntoPenny(10.30001));
System.out.println(roundDowntoPenny(10.3000));
System.out.println(roundDowntoPenny(10.20001));
System.out.println(roundDowntoPenny(10.2000));
}
Output:
10.3
10.3
10.2
10.19 // Not expected!
Of course, a method can be written which produces the output that we want. The problem is that it actually very difficult to do so (and to do so in every place where you need to manipulate prices).
For every numeral-system (base-10, base-2, base-16, etc.) with a finite number of digits, there are rationals that cannot be stored exactly. For example, 1/3 cannot be stored (with finite digits) in base-10. Similarly, 3/10 cannot be stored (with finite digits) in base-2.
If we needed to chose a numeral-system to store arbitrary rationals, it wouldn't matter what system we chose - any system chosen would have some rationals that couldn't be stored exactly.
However, humans began assigning prices to things way before the development of computer systems. Therefore, we see prices like 5.30 rather that 5 + 1/3. For example, our stock exchanges use decimal prices, which mean that they accept orders, and issue quotes, only in prices that can be represented in base-10. Likewise, it means that they can issue quotes and accept orders in prices that cannot be accurately represented in base-2.
By storing (transmitting, manipulating) those prices in base-2, we are essentially relying on rounding logic to always correctly round our (in-exact) base-2 (representation of) numbers back to their (exact) base-10 representation.