Description
NumberValue is hard (impossible?) to implement correctly for rational numbers because of Comparable<NumberValue>
Let me explain:
Let's suppose you are implementing your own NumberValue
class for rational numbers because you want to be able to perform monetary operations without rounding. Let's assume you have an instance of ⅓ and you need to implement Comparable<NumberValue>
.
The natural ordering should be:
0.33333
0.3̅
0.33334
But this is harder to implement than it sounds.
javax.money.NumberValue.compareTo(NumberValue)
is implemented using BigDecimal
conversion which is also used by org.javamoney.moneta.spi.DefaultNumberValue
. However the conversion from a rational number to a BigDecimal
includes rounding and we need to settle for a number of decimal places as we do not have a terminating decimal expansion. The issue is that any number of decimal places is wrong and leads to reordering of values. Let's say we settle for 5 decimal places and convert 0.3̅ to 0.33333. The issue is that 0.33333 is less than 0.333333 but 0.3̅ is greater than 0.333333. We could in theory look at the number of decimal places in the argument and use one additional decimal place. However this would make it impossible to keep the total ordering properties when the receiver is a DefaultNumberValue
and the argument is a custom rational NumberValue
.