This revision made January 05, 2013 23:08, by Anatole

JSR 354 - Further Implementation Notes

Based on earlier dialogs, the following implementation details produce the requirements for precision and performance:

- All numbers will be represented as one or two longs (depending on precision) for the mantissa and a single int for the base 10 exponent. For example, 12345.678 could be 12345678 mantissa and -3 exponent.
- It is possible for the result of a calculation to burst into the maximum internal representation (which is 2 longs for the mantissa and one int for the decimal).
- If the calculation involves adding two 4-digit values, with 2 decimal places precision, then internally the calculation will only need to perform one java-long addition.
- For all currency arithmetic, calculations are performed according to the full precision of the internal representation.
- Then if there is no rounding specified, and if the internal representation can't be expressed due to an overflow, then it will throw a Rounding exception. For example, $100/3=33.33333... will throw a Rounding exception.
- But if there is a rounding specified, then the calculation will be performed to the precision specified in the rounding (Please note that the Rounding associated with a Money instance should not be confused with the Rounding associated with a display instance. The Rounding for the Money instance represents the internal precision of the calculation, so for example 1/8 = .125. But if the Rounding specifies 2 decimal places then the internal representation would be truncated to .13 (using for this example USA rounding rules.)

It should be noted that several options have been considered concerning how to represent the value, without requiring the developer to be concerned with the internal representation. That can be accomplished by accepting the following API's for the Money class:

Money(Currency c, String value, Rounding r) and

Money(Currency c, double value, Rounding r).

When adding or subtracting two Money instances with different exponents, one of the moneys will need to shift its value to accomodate the other.

So for example 123.45 + 678.912, are represented internally as 12345 -2 and 678912 -3, so the addition will need to shift the lowest precision and perform as follows:

123450 -3 + 678912 -3

To minimize the number of shifts when performing addition and subtraction, we use a convention where by default, 10 decimal places are assumed.

Using that convention, if the value is 123.45, it will internally be represented as 123_4_500_000_000 -10. Since a long has about 19 digits of precision, that leaves 9 digits for the integer part of the value using one long, and 28 digits using 2 longs.

The exponent would be shifted to the right in extreme cases to allow more digits.

(This representation would accomodate the current gross world product (US$80,000,000,000,000) to 14 decimal places. That would even allow an accurate representation in Korean Wons.

If you use the String constructor, there is a performance hit on converting that to an internal representation

If you use the double constructor, there is a smaller performance hit on the conversion, but you are agreeing to the value as supplied, assuming it is precise.

A 3rd constructor that allows the user to specify an internal precision, for example as a long[3] array will also be provided.

Money(Currency c, long[] mantissa, int exponent, Rounding r)

Which ever constructor is used, the Money class will automatically allocate the internal representation based on the value and Rounding.

This suggests several classes and an internal representation:

1. Money - an immutable value object containing a value and a Currency, as well as an optional Rounding

2. Rounding - an immutable object that is included in a Money object on construction.

3. RoundingAlgorithm - an extendable Enum containing all known rounding algorithms

4. RoundingException (Checked Exception) - thrown when a calculation produces a value that exceeds the internal representation, and when no rounding is specified to handle that overflow.

5. Currency (or CurrencyUnit, should we loosely adjust to 310 naming here and avoid ambiguity with java.util.Currency) - an interface, allowing different types of currencies including SPI-style custom currencies, e.g. for Social Networks, Gaming or Online Discount Tickets

6. CurrencyConverter - a class or interface taking necessary attributes for currency conversion, at least a Money object and target Currency, plus whatever is necessary, e.g. Time/Date (here useful 310 references seem like a good idea;-)
In the likely event, CurrencyConverter won't be the only element needed, at least for these a **sub-package** like "convert" (see JSF) or "converter" (see JavaFX) seems highly advisable.

7. ExchangeRate - potentially one or more helper objects to CurrencyConverter in the same package, see above.

8. format - a sub-package to deal with Money and Currency formatting.

Difference compared to previous revision

<span><span style="text-decoration:underline;color:green">=<img align="right" src="http://asset-1.java.net/attachments/images/project/javamoney.png?20121214.f926c51"/> <br/>JSR 354 - Further Implementation Notes<br/><br/><br/>
</span>Based on earlier dialogs, the following implementation details produce the requirements for precision and performance:<span style="text-decoration:line-through;color:red"><br/></span>
<span style="text-decoration:line-through;color:red">
</span>Based on earlier dialogs, the following implementation details produce the requirements for precision and performance:
<span style="text-decoration:underline;color:green">* </span>All numbers will be represented as one or two longs (depending on precision) for the mantissa and a single int for the base 10 exponent. For example, 12345.678 could be 12345678 mantissa and -3 exponent.<span style="text-decoration:line-through;color:red"><br/></span>
<span style="text-decoration:line-through;color:red">
</span>All numbers will be represented as one or two longs (depending on precision) for the mantissa and a single int for the base 10 exponent. For example, 12345.678 could be 12345678 mantissa and -3 exponent.
<span style="text-decoration:underline;color:green">* </span>It is possible for the result of a calculation to burst into the maximum internal representation (which is 2 longs for the mantissa and one int for the decimal).<span style="text-decoration:line-through;color:red"><br/></span>
<span style="text-decoration:line-through;color:red">
</span>It is possible for the result of a calculation to burst into the maximum internal representation (which is 2 longs for the mantissa and one int for the decimal).
<span style="text-decoration:underline;color:green">* </span>If the calculation involves adding two 4-digit values, with 2 decimal places precision, then internally the calculation will only need to perform one java-long addition.<span style="text-decoration:line-through;color:red"><br/></span>
<span style="text-decoration:line-through;color:red">
</span>If the calculation involves adding two 4-digit values, with 2 decimal places precision, then internally the calculation will only need to perform one java-long addition.
<span style="text-decoration:underline;color:green">* </span>For all currency arithmetic, calculations are performed according to the full precision of the internal representation.<span style="text-decoration:line-through;color:red"><br/></span>For all currency arithmetic, calculations are performed according to the full precision of the internal representation.
<span style="text-decoration:underline;color:green">* </span>
Then if there is no rounding specified, and if the internal representation can't be expressed due to an overflow, then it will throw a Rounding exception<span style="text-decoration:line-through;color:red"><br/>
</span>Then if there is no rounding specified, and if the internal representation can't be expressed due to an overflow, then it will throw a Rounding exception<span style="text-decoration:underline;color:green">. </span>For example, $100/3=33.33333... will throw a Rounding exception<span style="text-decoration:line-through;color:red"><br/></span><span style="text-decoration:underline;color:green">.</span>
<span style="text-decoration:line-through;color:red"><br/>
</span><span style="text-decoration:underline;color:green">* </span>But if there is a rounding specified, then the calculation will be performed to the precision specified in the rounding<span style="text-decoration:line-through;color:red">.<br/>
</span><span style="text-decoration:underline;color:green"> </span>(Please note that the Rounding associated with a Money instance should not be confused with the Rounding associated with a display instance. The Rounding for the Money instance represents the internal precision of the calculation, so for example 1/8 = .125. But if the Rounding specifies 2 decimal places then the internal representation would be truncated to .13 (using for this example USA rounding rules.)
It should be noted that several options have been considered concerning how to represent the value, without requiring the developer to be concerned with the internal representation.<span style="text-decoration:line-through;color:red"><br/>
</span><span style="text-decoration:underline;color:green"> </span>That can be accomplished by accepting the following API's for the Money class:<br/>
Money(Currency c, String value, Rounding r) and<br/>
Money(Currency c, double value, Rounding r).<br/>
<span>

Please Confirm