/** * Gets the scale of the {@code BigDecimal} amount. * <p> * The scale has the same meaning as in {@link BigDecimal}. * Positive values represent the number of decimal places in use. * For example, a scale of 2 means that the money will have two decimal places * such as 'USD 43.25'. * <p> * For {@code Money}, the scale is fixed and always matches that of the currency. * * @return the scale in use, typically 2 but could be 0, 1 and 3 */ public int getScale() { return money.getScale(); }
private void writeBigMoney(ObjectOutput out, BigMoney obj) throws IOException { writeCurrency(out, obj.getCurrencyUnit()); byte[] bytes = obj.getAmount().unscaledValue().toByteArray(); out.writeInt(bytes.length); out.write(bytes); out.writeInt(obj.getScale()); }
/** * Returns a copy of this monetary value with the amount added retaining * the scale by rounding the result. * <p> * The scale of the result will be the same as the scale of this instance. * For example,'USD 25.95' plus '3.021d' gives 'USD 28.97' with most rounding modes. * <p> * The amount is converted via {@link BigDecimal#valueOf(double)} which yields * the most expected answer for most programming scenarios. * Any {@code double} literal in code will be converted to * exactly the same BigDecimal with the same scale. * For example, the literal '1.45d' will be converted to '1.45'. * <p> * This instance is immutable and unaffected by this method. * * @param amountToAdd the monetary value to add, not null * @param roundingMode the rounding mode to use to adjust the scale, not null * @return the new instance with the input amount added, never null */ public BigMoney plusRetainScale(double amountToAdd, RoundingMode roundingMode) { if (amountToAdd == 0) { return this; } BigDecimal newAmount = amount.add(BigDecimal.valueOf(amountToAdd)); newAmount = newAmount.setScale(getScale(), roundingMode); return BigMoney.of(currency, newAmount); }
/** * Returns a copy of this monetary value with the amount subtracted retaining * the scale by rounding the result. * <p> * The scale of the result will be the same as the scale of this instance. * For example,'USD 25.95' minus '3.029d' gives 'USD 22.92' with most rounding modes. * <p> * The amount is converted via {@link BigDecimal#valueOf(double)} which yields * the most expected answer for most programming scenarios. * Any {@code double} literal in code will be converted to * exactly the same BigDecimal with the same scale. * For example, the literal '1.45d' will be converted to '1.45'. * <p> * This instance is immutable and unaffected by this method. * * @param amountToSubtract the monetary value to add, not null * @param roundingMode the rounding mode to use to adjust the scale, not null * @return the new instance with the input amount subtracted, never null */ public BigMoney minusRetainScale(double amountToSubtract, RoundingMode roundingMode) { if (amountToSubtract == 0) { return this; } BigDecimal newAmount = amount.subtract(BigDecimal.valueOf(amountToSubtract)); newAmount = newAmount.setScale(getScale(), roundingMode); return BigMoney.of(currency, newAmount); }
/** * Returns a copy of this monetary value with the amount added retaining * the scale by rounding the result. * <p> * The scale of the result will be the same as the scale of this instance. * For example,'USD 25.95' plus '3.021' gives 'USD 28.97' with most rounding modes. * <p> * This instance is immutable and unaffected by this method. * * @param amountToAdd the monetary value to add, not null * @param roundingMode the rounding mode to use to adjust the scale, not null * @return the new instance with the input amount added, never null */ public BigMoney plusRetainScale(BigDecimal amountToAdd, RoundingMode roundingMode) { MoneyUtils.checkNotNull(amountToAdd, "Amount must not be null"); if (amountToAdd.compareTo(BigDecimal.ZERO) == 0) { return this; } BigDecimal newAmount = amount.add(amountToAdd); newAmount = newAmount.setScale(getScale(), roundingMode); return BigMoney.of(currency, newAmount); }
/** * Returns a copy of this monetary value with the amount subtracted retaining * the scale by rounding the result. * <p> * The scale of the result will be the same as the scale of this instance. * For example,'USD 25.95' minus '3.029' gives 'USD 22.92' with most rounding modes. * <p> * This instance is immutable and unaffected by this method. * * @param amountToSubtract the monetary value to add, not null * @param roundingMode the rounding mode to use to adjust the scale, not null * @return the new instance with the input amount subtracted, never null */ public BigMoney minusRetainScale(BigDecimal amountToSubtract, RoundingMode roundingMode) { MoneyUtils.checkNotNull(amountToSubtract, "Amount must not be null"); if (amountToSubtract.compareTo(BigDecimal.ZERO) == 0) { return this; } BigDecimal newAmount = amount.subtract(amountToSubtract); newAmount = newAmount.setScale(getScale(), roundingMode); return BigMoney.of(currency, newAmount); }
/** * Returns a copy of this monetary value rounded to the specified scale without * changing the current scale. * <p> * Scale is described in {@link BigDecimal} and represents the point below which * the monetary value is zero. Negative scales round increasingly large numbers. * Unlike {@link #withScale(int)}, this scale of the result is unchanged. * <ul> * <li>Rounding 'EUR 45.23' to a scale of -1 returns 40.00 or 50.00 depending on the rounding mode. * <li>Rounding 'EUR 45.23' to a scale of 0 returns 45.00 or 46.00 depending on the rounding mode. * <li>Rounding 'EUR 45.23' to a scale of 1 returns 45.20 or 45.30 depending on the rounding mode. * <li>Rounding 'EUR 45.23' to a scale of 2 has no effect (it already has that scale). * <li>Rounding 'EUR 45.23' to a scale of 3 has no effect (the scale is not increased). * </ul> * This instance is immutable and unaffected by this method. * * @param scale the new scale * @param roundingMode the rounding mode to use, not null * @return the new instance with the amount converted to be positive, never null * @throws ArithmeticException if the rounding fails */ public BigMoney rounded(int scale, RoundingMode roundingMode) { MoneyUtils.checkNotNull(roundingMode, "RoundingMode must not be null"); if (scale >= getScale()) { return this; } int currentScale = amount.scale(); BigDecimal newAmount = amount.setScale(scale, roundingMode).setScale(currentScale); return BigMoney.of(currency, newAmount); }
/** * Returns a copy of this monetary value converted into another currency * using the specified conversion rate, with a rounding mode used to adjust * the decimal places in the result. * <p> * The result will have the same scale as this instance even though it will * be in a different currency. * <p> * This instance is immutable and unaffected by this method. * * @param currency the new currency, not null * @param conversionMultipler the conversion factor between the currencies, not null * @param roundingMode the rounding mode to use to bring the decimal places back in line, not null * @return the new multiplied instance, never null * @throws IllegalArgumentException if the currency is the same as this currency and the * conversion is not one; or if the conversion multiplier is negative * @throws ArithmeticException if the rounding fails */ public BigMoney convertRetainScale(CurrencyUnit currency, BigDecimal conversionMultipler, RoundingMode roundingMode) { return convertedTo(currency, conversionMultipler).withScale(getScale(), roundingMode); }
/** * Returns a copy of this monetary value multiplied by the specified value * using the specified rounding mode to adjust the scale of the result. * <p> * This multiplies this money by the specified value, retaining the scale of this money. * This will frequently lose precision, hence the need for a rounding mode. * For example, 'USD 1.13' multiplied by '2.5' and rounding down gives 'USD 2.82'. * <p> * This instance is immutable and unaffected by this method. * * @param valueToMultiplyBy the scalar value to multiply by, not null * @param roundingMode the rounding mode to use to bring the decimal places back in line, not null * @return the new multiplied instance, never null * @throws ArithmeticException if the rounding fails */ public BigMoney multiplyRetainScale(BigDecimal valueToMultiplyBy, RoundingMode roundingMode) { MoneyUtils.checkNotNull(valueToMultiplyBy, "Multiplier must not be null"); MoneyUtils.checkNotNull(roundingMode, "RoundingMode must not be null"); if (valueToMultiplyBy.compareTo(BigDecimal.ONE) == 0) { return this; } BigDecimal newAmount = amount.multiply(valueToMultiplyBy); newAmount = newAmount.setScale(getScale(), roundingMode); return BigMoney.of(currency, newAmount); }
@Override protected BigMoney fromConvertedColumns(Object[] convertedColumns) { CurrencyUnit currencyUnitPart = (CurrencyUnit) convertedColumns[0]; Long amountMajorPart = (Long) convertedColumns[1]; BigMoney theMoney = BigMoney.ofMajor(currencyUnitPart, amountMajorPart); if (theMoney.getScale() < currencyUnitPart.getDecimalPlaces()) { theMoney = theMoney.withCurrencyScale(); } return theMoney; }
@Override public BigMoney fromNonNullValue(Long value) { BigMoney theMoney = BigMoney.ofMajor(currencyUnit, value); if (theMoney.getScale() < currencyUnit.getDecimalPlaces()) { theMoney = theMoney.withCurrencyScale(); } return theMoney; }
@Override protected BigMoney fromConvertedColumns(Object[] convertedColumns) { CurrencyUnit currencyUnitPart = (CurrencyUnit) convertedColumns[0]; Long amountMajorPart = (Long) convertedColumns[1]; BigMoney theMoney = BigMoney.ofMajor(currencyUnitPart, amountMajorPart); if (theMoney.getScale() < currencyUnitPart.getDecimalPlaces()) { theMoney = theMoney.withCurrencyScale(); } return theMoney; }