Decimal objects are immutable. Many operations return new Decimal objects.
Many will be surprised that this class does not make any reference to currency. The reason for this is adding currency would render this class a poor building block. Building block objects such as Date, Integer, and so on, are atomic, in the sense of representing a single piece of data. They correspond to a single column in a table, or a single form control. If the currency were included in this class, then it would no longer be atomic, and it could not be treated by WEB4J as any other building block class. However, allowing this class to be treated like any other building block class is highly advantageous.
If a feature needs to explicitly distinguish between multiple currencies such as US Dollars and Japanese Yen, then a Decimal object will need to be paired by the caller with a second item representing the underlying currency (perhaps modeled as an Id). See the {@link Currency} class for more information.
The {@link #init(RoundingMode,int)} method is called upon startup.It takes a parameter which specifies the number of decimal places. It is used only for rounding the results of times and div operations. It is not used to validate the number of decimals in items passed to the Decimal constructor.
As usual, operations can be performed on two items having a different number of decimal places. For example, these operations are valid (using an informal, ad hoc notation) :
10 + 1.23 = 11.23 10.00 + 1.23 = 11.23 10 - 1.23 = 8.77 (10 > 1.23) => trueThis corresponds to typical user expectations.
Note that {@link #equals(Object)} is unusual in that it is the only method sensitive to the exact number of decimal places, while {@link #eq(Decimal)} is not. That is,
10.equals(10.00) => false 10.eq(10.00) => true
The times and div operations are different, since the result can have a larger number of decimals than usual. For example, when dealing with US Dollars, the result
$10.00 x 0.1256 = $1.256has more than two decimals. In such cases, this class will round results of multiplication and division, using the setting passed to {@link #init(RoundingMode,int)}. This policy likely conforms to the expectations of most end users. The {@link #times(long)} method is an exception to this rule.
The {@link #init(RoundingMode,int)} method takes two parameters.One controls the rounding policy, and the other controls the number of decimals to use by default. When the default number of decimals needs to be overridden, you must use the {@link #changeTimesDivDecimals(int)} method.
Example :
if ( amount.lt(hundred) ) { cost = amount.times(price); }
In short, the double versions are best suited when using hard-coded values for factors and divisors, while the Decimal versions are suited for the (more common) case of using values coming from the database or user input.
Using Decimal is the preferred form, since there are many pitfalls associated with double. The double form has been retained since it's more convenient for the caller in some cases, and one of the goals of this class is to allow terse mathematical expressions.
|
|
|
|
|
|
|
|