mirror of
https://github.com/moparisthebest/mailiverse
synced 2024-12-01 12:32:15 -05:00
2846 lines
104 KiB
Java
2846 lines
104 KiB
Java
/*
|
|
* Copyright 2009 Google Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
* use this file except in compliance with the License. You may obtain a copy of
|
|
* the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations under
|
|
* the License.
|
|
*/
|
|
|
|
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with this
|
|
* work for additional information regarding copyright ownership. The ASF
|
|
* licenses this file to You under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations under
|
|
* the License.
|
|
*
|
|
* INCLUDES MODIFICATIONS BY RICHARD ZSCHECH AS WELL AS GOOGLE.
|
|
*/
|
|
package java.math;
|
|
|
|
import com.google.gwt.core.client.JavaScriptObject;
|
|
|
|
import java.io.Serializable;
|
|
|
|
/**
|
|
* This class represents immutable arbitrary precision decimal numbers. Each
|
|
* {@code BigDecimal} instance is represented with a unscaled arbitrary
|
|
* precision mantissa (the unscaled value) and a scale. The value of the {@code
|
|
* BigDecimal} is {@code unscaledValue} 10^(-{@code scale}).
|
|
*/
|
|
public class BigDecimal extends Number implements Comparable<BigDecimal>,
|
|
Serializable {
|
|
|
|
/**
|
|
* One more than the number of bits which can be stored in {@link #smallValue}.
|
|
*/
|
|
private static final int SMALL_VALUE_BITS = 54;
|
|
|
|
/**
|
|
* The constant one as a {@code BigDecimal}.
|
|
*/
|
|
public static final BigDecimal ONE = new BigDecimal(1, 0);
|
|
|
|
/**
|
|
* Rounding mode to round towards positive infinity. For positive values this
|
|
* rounding mode behaves as {@link #ROUND_UP}, for negative values as
|
|
* {@link #ROUND_DOWN}.
|
|
*
|
|
* @see RoundingMode#CEILING
|
|
*/
|
|
public static final int ROUND_CEILING = 2;
|
|
|
|
/**
|
|
* Rounding mode where the values are rounded towards zero.
|
|
*
|
|
* @see RoundingMode#DOWN
|
|
*/
|
|
public static final int ROUND_DOWN = 1;
|
|
|
|
/**
|
|
* Rounding mode to round towards negative infinity. For positive values this
|
|
* rounding mode behaves as {@link #ROUND_DOWN}, for negative values as
|
|
* {@link #ROUND_UP}.
|
|
*
|
|
* @see RoundingMode#FLOOR
|
|
*/
|
|
public static final int ROUND_FLOOR = 3;
|
|
|
|
/**
|
|
* Rounding mode where values are rounded towards the nearest neighbor. Ties
|
|
* are broken by rounding down.
|
|
*
|
|
* @see RoundingMode#HALF_DOWN
|
|
*/
|
|
public static final int ROUND_HALF_DOWN = 5;
|
|
|
|
/**
|
|
* Rounding mode where values are rounded towards the nearest neighbor. Ties
|
|
* are broken by rounding to the even neighbor.
|
|
*
|
|
* @see RoundingMode#HALF_EVEN
|
|
*/
|
|
public static final int ROUND_HALF_EVEN = 6;
|
|
|
|
/**
|
|
* Rounding mode where values are rounded towards the nearest neighbor. Ties
|
|
* are broken by rounding up.
|
|
*
|
|
* @see RoundingMode#HALF_UP
|
|
*/
|
|
public static final int ROUND_HALF_UP = 4;
|
|
|
|
/**
|
|
* Rounding mode where the rounding operations throws an {@code
|
|
* ArithmeticException} for the case that rounding is necessary, i.e. for the
|
|
* case that the value cannot be represented exactly.
|
|
*
|
|
* @see RoundingMode#UNNECESSARY
|
|
*/
|
|
public static final int ROUND_UNNECESSARY = 7;
|
|
|
|
/**
|
|
* Rounding mode where positive values are rounded towards positive infinity
|
|
* and negative values towards negative infinity.
|
|
*
|
|
* @see RoundingMode#UP
|
|
*/
|
|
public static final int ROUND_UP = 0;
|
|
|
|
/**
|
|
* The constant ten as a {@code BigDecimal}.
|
|
*/
|
|
public static final BigDecimal TEN = new BigDecimal(10, 0);
|
|
|
|
/**
|
|
* The constant zero as a {@code BigDecimal}.
|
|
*/
|
|
public static final BigDecimal ZERO = new BigDecimal(0, 0);
|
|
|
|
protected static JavaScriptObject unscaledRegex;
|
|
|
|
private static final int BI_SCALED_BY_ZERO_LENGTH = 11;
|
|
|
|
/**
|
|
* An array with the first <code>BigInteger</code> scaled by zero. (
|
|
* <code>[0,0],[1,0],...,[10,0]</code>).
|
|
*/
|
|
private static final BigDecimal BI_SCALED_BY_ZERO[] = new BigDecimal[BI_SCALED_BY_ZERO_LENGTH];
|
|
|
|
/**
|
|
* An array filled with characters <code>'0'</code>.
|
|
*/
|
|
private static final char[] CH_ZEROS = new char[100];
|
|
|
|
private static final double[] DOUBLE_FIVE_POW = new double[] {
|
|
1D, 5D, 25D, 125D, 625D, 3125D, 15625D, 78125D, 390625D, 1953125D,
|
|
9765625D, 48828125D, 244140625D, 1220703125D, 6103515625D, 30517578125D,
|
|
152587890625D, 762939453125D, 3814697265625D, 19073486328125D,
|
|
95367431640625D, 476837158203125D, 2384185791015625D,};
|
|
|
|
private static final int[] DOUBLE_FIVE_POW_BIT_LENGTH = new int[DOUBLE_FIVE_POW.length];
|
|
|
|
/**
|
|
* An array with powers of ten that fit in the type <code>double</code> (
|
|
* <code>10^0,10^1,...,10^18</code>).
|
|
*/
|
|
private static final double[] DOUBLE_TEN_POW = new double[] {
|
|
1D, 10D, 100D, 1000D, 10000D, 100000D, 1000000D, 10000000D, 100000000D,
|
|
1000000000D, 10000000000D, 100000000000D, 1000000000000D,
|
|
10000000000000D, 100000000000000D, 1000000000000000D,
|
|
10000000000000000D,};
|
|
|
|
private static final int[] DOUBLE_TEN_POW_BIT_LENGTH = new int[DOUBLE_TEN_POW.length];
|
|
|
|
/**
|
|
* An array with powers of five that fit in the type <code>double</code> (
|
|
* <code>5^0,5^1,...,5^27</code>).
|
|
*/
|
|
private static final BigInteger FIVE_POW[];
|
|
|
|
/**
|
|
* The double closest to <code>Math.log(2.0d)</code>.
|
|
*/
|
|
private static final double LOG2 = 0.6931471805599453d;
|
|
|
|
/**
|
|
* The double closest to <code>Log10(2)</code>.
|
|
*/
|
|
private static final double LOG10_2 = 0.3010299956639812;
|
|
|
|
/**
|
|
* The double closer to <code>Math.pow(2, 47)</code>.
|
|
*/
|
|
private static final double POW47 = 140737488355328d;
|
|
|
|
/**
|
|
* This is the serialVersionUID used by the sun implementation.
|
|
*/
|
|
private static final long serialVersionUID = 6108874887143696463L;
|
|
|
|
/**
|
|
* An array with powers of ten that fit in the type <code>double</code> (
|
|
* <code>10^0,10^1,...,10^18</code>).
|
|
*/
|
|
private static final BigInteger TEN_POW[];
|
|
|
|
/**
|
|
* An array with the zero number scaled by the first positive scales. (
|
|
* <code>0*10^0, 0*10^1, ..., 0*10^10</code>).
|
|
*/
|
|
private static final BigDecimal ZERO_SCALED_BY[] = new BigDecimal[11];
|
|
|
|
static {
|
|
// To fill all static arrays.
|
|
int i = 0;
|
|
|
|
for (; i < ZERO_SCALED_BY.length; i++) {
|
|
BI_SCALED_BY_ZERO[i] = new BigDecimal(i, 0);
|
|
ZERO_SCALED_BY[i] = new BigDecimal(0, i);
|
|
CH_ZEROS[i] = '0';
|
|
}
|
|
|
|
for (; i < CH_ZEROS.length; i++) {
|
|
CH_ZEROS[i] = '0';
|
|
}
|
|
for (int j = 0; j < DOUBLE_FIVE_POW_BIT_LENGTH.length; j++) {
|
|
DOUBLE_FIVE_POW_BIT_LENGTH[j] = bitLength(DOUBLE_FIVE_POW[j]);
|
|
}
|
|
for (int j = 0; j < DOUBLE_TEN_POW_BIT_LENGTH.length; j++) {
|
|
DOUBLE_TEN_POW_BIT_LENGTH[j] = bitLength(DOUBLE_TEN_POW[j]);
|
|
}
|
|
|
|
// Taking the references of useful powers.
|
|
TEN_POW = Multiplication.bigTenPows;
|
|
FIVE_POW = Multiplication.bigFivePows;
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} instance whose value is equal to {@code
|
|
* val}. The new decimal is constructed as if the {@code BigDecimal(String)}
|
|
* constructor is called with an argument which is equal to {@code
|
|
* Double.toString(val)}. For example, {@code valueOf("0.1")} is converted to
|
|
* (unscaled=1, scale=1), although the double {@code 0.1} cannot be
|
|
* represented exactly as a double value. In contrast to that, a new {@code
|
|
* BigDecimal(0.1)} instance has the value {@code
|
|
* 0.1000000000000000055511151231257827021181583404541015625} with an unscaled
|
|
* value {@code 1000000000000000055511151231257827021181583404541015625} and
|
|
* the scale {@code 55}.
|
|
*
|
|
* @param val double value to be converted to a {@code BigDecimal}.
|
|
* @return {@code BigDecimal} instance with the value {@code val}.
|
|
* @throws NumberFormatException if {@code val} is infinite or {@code val} is
|
|
* not a number
|
|
*/
|
|
public static BigDecimal valueOf(double val) {
|
|
if (Double.isInfinite(val) || Double.isNaN(val)) {
|
|
// math.03=Infinity or NaN
|
|
throw new NumberFormatException("Infinite or NaN"); //$NON-NLS-1$
|
|
}
|
|
return new BigDecimal(Double.toString(val));
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} instance whose value is equal to {@code
|
|
* unscaledVal}. The scale of the result is {@code 0}, and its unscaled value
|
|
* is {@code unscaledVal}.
|
|
*
|
|
* @param unscaledVal value to be converted to a {@code BigDecimal}.
|
|
* @return {@code BigDecimal} instance with the value {@code unscaledVal}.
|
|
*/
|
|
public static BigDecimal valueOf(long unscaledVal) {
|
|
if ((unscaledVal >= 0) && (unscaledVal < BI_SCALED_BY_ZERO_LENGTH)) {
|
|
return BI_SCALED_BY_ZERO[(int) unscaledVal];
|
|
}
|
|
return new BigDecimal(unscaledVal, 0);
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} instance whose value is equal to {@code
|
|
* unscaledVal} 10^(-{@code scale}). The scale of the result is {@code scale},
|
|
* and its unscaled value is {@code unscaledVal}.
|
|
*
|
|
* @param unscaledVal unscaled value to be used to construct the new {@code
|
|
* BigDecimal}.
|
|
* @param scale scale to be used to construct the new {@code BigDecimal}.
|
|
* @return {@code BigDecimal} instance with the value {@code unscaledVal}*
|
|
* 10^(-{@code unscaledVal}).
|
|
*/
|
|
public static BigDecimal valueOf(long unscaledVal, int scale) {
|
|
if (scale == 0) {
|
|
return valueOf(unscaledVal);
|
|
}
|
|
if ((unscaledVal == 0) && (scale >= 0) && (scale < ZERO_SCALED_BY.length)) {
|
|
return ZERO_SCALED_BY[scale];
|
|
}
|
|
return new BigDecimal(unscaledVal, scale);
|
|
}
|
|
|
|
private static BigDecimal addAndMult10(BigDecimal thisValue,
|
|
BigDecimal augend, double diffScale) {
|
|
if (diffScale < DOUBLE_TEN_POW.length
|
|
&& Math.max(thisValue.bitLength, augend.bitLength
|
|
+ DOUBLE_TEN_POW_BIT_LENGTH[(int) diffScale]) + 1
|
|
< SMALL_VALUE_BITS) {
|
|
return valueOf(thisValue.smallValue + augend.smallValue
|
|
* DOUBLE_TEN_POW[(int) diffScale], thisValue.scale);
|
|
}
|
|
return new BigDecimal(thisValue.getUnscaledValue().add(
|
|
Multiplication.multiplyByTenPow(augend.getUnscaledValue(),
|
|
(int) diffScale)), thisValue.scale);
|
|
}
|
|
|
|
private static int bitLength(double value) {
|
|
// if |value| is less than 2^47, use log
|
|
if (value > -POW47 && value < POW47) {
|
|
if (value == 0.0) {
|
|
// special-case zero, otherwise we get -INFINITY below
|
|
return 0;
|
|
}
|
|
boolean negative = (value < 0.0);
|
|
if (negative) {
|
|
value = -value;
|
|
}
|
|
int result = (int) Math.floor(Math.log(value) / LOG2);
|
|
if (!negative || value != Math.pow(2, result)) {
|
|
result++;
|
|
}
|
|
return result;
|
|
}
|
|
return bitLength((long) value);
|
|
}
|
|
|
|
private static int bitLength(long value) {
|
|
if (value < 0) {
|
|
value = ~value;
|
|
}
|
|
return 64 - Long.numberOfLeadingZeros(value);
|
|
}
|
|
|
|
private static BigDecimal divideBigIntegers(BigInteger scaledDividend,
|
|
BigInteger scaledDivisor, int scale, RoundingMode roundingMode) {
|
|
|
|
BigInteger[] quotAndRem = scaledDividend.divideAndRemainder(scaledDivisor); // quotient
|
|
// and
|
|
// remainder
|
|
// If after division there is a remainder...
|
|
BigInteger quotient = quotAndRem[0];
|
|
BigInteger remainder = quotAndRem[1];
|
|
if (remainder.signum() == 0) {
|
|
return new BigDecimal(quotient, scale);
|
|
}
|
|
int sign = scaledDividend.signum() * scaledDivisor.signum();
|
|
int compRem; // 'compare to remainder'
|
|
if (scaledDivisor.bitLength() < SMALL_VALUE_BITS) {
|
|
long rem = remainder.longValue();
|
|
long divisor = scaledDivisor.longValue();
|
|
compRem = longCompareTo(Math.abs(rem) << 1, Math.abs(divisor));
|
|
// To look if there is a carry
|
|
compRem = roundingBehavior(quotient.testBit(0) ? 1 : 0, sign
|
|
* (5 + compRem), roundingMode);
|
|
|
|
} else {
|
|
// Checking if: remainder * 2 >= scaledDivisor
|
|
compRem = remainder.abs().shiftLeftOneBit().compareTo(scaledDivisor.abs());
|
|
compRem = roundingBehavior(quotient.testBit(0) ? 1 : 0, sign
|
|
* (5 + compRem), roundingMode);
|
|
}
|
|
if (compRem != 0) {
|
|
if (quotient.bitLength() < SMALL_VALUE_BITS) {
|
|
return valueOf(quotient.longValue() + compRem, scale);
|
|
}
|
|
quotient = quotient.add(BigInteger.valueOf(compRem));
|
|
return new BigDecimal(quotient, scale);
|
|
}
|
|
// Constructing the result with the appropriate unscaled value
|
|
return new BigDecimal(quotient, scale);
|
|
}
|
|
|
|
private static BigDecimal dividePrimitiveDoubles(double scaledDividend,
|
|
double scaledDivisor, int scale, RoundingMode roundingMode) {
|
|
double quotient = intDivide(scaledDividend, scaledDivisor);
|
|
double remainder = scaledDividend % scaledDivisor;
|
|
int sign = Double.compare(scaledDividend * scaledDivisor, 0.0);
|
|
if (remainder != 0) {
|
|
// Checking if: remainder * 2 >= scaledDivisor
|
|
int compRem; // 'compare to remainder'
|
|
compRem = Double.compare(Math.abs(remainder) * 2,
|
|
Math.abs(scaledDivisor));
|
|
// To look if there is a carry
|
|
quotient += roundingBehavior(((int) quotient) & 1, sign * (5 + compRem),
|
|
roundingMode);
|
|
}
|
|
// Constructing the result with the appropriate unscaled value
|
|
return valueOf(quotient, scale);
|
|
}
|
|
|
|
private static double intDivide(double dividend, double divisor) {
|
|
double quotient = dividend / divisor;
|
|
return quotient > 0 ? Math.floor(quotient) : Math.ceil(quotient);
|
|
}
|
|
|
|
private static int longCompareTo(long a, long b) {
|
|
return Long.signum(a - b);
|
|
}
|
|
|
|
private static native double parseUnscaled(String str) /*-{
|
|
var unscaledRegex = @java.math.BigDecimal::unscaledRegex;
|
|
if (!unscaledRegex) {
|
|
unscaledRegex = @java.math.BigDecimal::unscaledRegex = /^[+-]?\d*$/i;
|
|
}
|
|
if (unscaledRegex.test(str)) {
|
|
return parseInt(str, 10);
|
|
} else {
|
|
return Number.NaN;
|
|
}
|
|
}-*/;
|
|
|
|
/**
|
|
* Return an increment that can be -1,0 or 1, depending of {@code
|
|
* roundingMode}.
|
|
*
|
|
* @param parityBit can be 0 or 1, it's only used in the case {@code
|
|
* HALF_EVEN}
|
|
* @param fraction the mantisa to be analyzed
|
|
* @param roundingMode the type of rounding
|
|
* @return the carry propagated after rounding
|
|
*/
|
|
private static int roundingBehavior(int parityBit, int fraction,
|
|
RoundingMode roundingMode) {
|
|
int increment = 0; // the carry after rounding
|
|
|
|
switch (roundingMode) {
|
|
case UNNECESSARY:
|
|
if (fraction != 0) {
|
|
// math.08=Rounding necessary
|
|
throw new ArithmeticException("Rounding necessary"); //$NON-NLS-1$
|
|
}
|
|
break;
|
|
case UP:
|
|
increment = Integer.signum(fraction);
|
|
break;
|
|
case DOWN:
|
|
break;
|
|
case CEILING:
|
|
increment = Math.max(Integer.signum(fraction), 0);
|
|
break;
|
|
case FLOOR:
|
|
increment = Math.min(Integer.signum(fraction), 0);
|
|
break;
|
|
case HALF_UP:
|
|
if (Math.abs(fraction) >= 5) {
|
|
increment = Integer.signum(fraction);
|
|
}
|
|
break;
|
|
case HALF_DOWN:
|
|
if (Math.abs(fraction) > 5) {
|
|
increment = Integer.signum(fraction);
|
|
}
|
|
break;
|
|
case HALF_EVEN:
|
|
if (Math.abs(fraction) + parityBit > 5) {
|
|
increment = Integer.signum(fraction);
|
|
}
|
|
break;
|
|
}
|
|
return increment;
|
|
}
|
|
|
|
/**
|
|
* It tests if a scale of type {@code long} fits in 32 bits. It returns the
|
|
* same scale being casted to {@code int} type when is possible, otherwise
|
|
* throws an exception.
|
|
*
|
|
* @param doubleScale a double bit scale
|
|
* @return a 32 bit scale when is possible
|
|
* @throws ArithmeticException when {@code scale} doesn't fit in {@code int}
|
|
* type
|
|
* @see #scale
|
|
*/
|
|
private static int toIntScale(double doubleScale) {
|
|
if (doubleScale < Integer.MIN_VALUE) {
|
|
// math.09=Overflow
|
|
throw new ArithmeticException("Overflow"); //$NON-NLS-1$
|
|
} else if (doubleScale > Integer.MAX_VALUE) {
|
|
// math.0A=Underflow
|
|
throw new ArithmeticException("Underflow"); //$NON-NLS-1$
|
|
} else {
|
|
return (int) doubleScale;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Convert a double to a string with {@code digits} precision. The resulting
|
|
* string may still be in exponential notation.
|
|
*
|
|
* @param d double value
|
|
* @param digits number of digits of precision to include
|
|
* @return non-localized string representation of {@code d}
|
|
*/
|
|
private static native String toPrecision(double d, int digits) /*-{
|
|
return d.toPrecision(digits);
|
|
}-*/;
|
|
|
|
private static BigDecimal valueOf(double smallValue, double scale) {
|
|
return new BigDecimal(smallValue, scale);
|
|
}
|
|
|
|
/**
|
|
* It returns the value 0 with the most approximated scale of type {@code int}
|
|
* . if {@code longScale > Integer.MAX_VALUE} the scale will be {@code
|
|
* Integer.MAX_VALUE}; if {@code longScale < Integer.MIN_VALUE} the scale will
|
|
* be {@code Integer.MIN_VALUE}; otherwise {@code longScale} is casted to the
|
|
* type {@code int}.
|
|
*
|
|
* @param doubleScale the scale to which the value 0 will be scaled.
|
|
* @return the value 0 scaled by the closer scale of type {@code int}.
|
|
* @see #scale
|
|
*/
|
|
private static BigDecimal zeroScaledBy(double doubleScale) {
|
|
if (doubleScale == (int) doubleScale) {
|
|
return valueOf(0, (int) doubleScale);
|
|
}
|
|
if (doubleScale >= 0) {
|
|
return new BigDecimal(0, Integer.MAX_VALUE);
|
|
}
|
|
return new BigDecimal(0, Integer.MIN_VALUE);
|
|
}
|
|
|
|
private transient int bitLength;
|
|
|
|
/**
|
|
* Cache for the hash code.
|
|
*/
|
|
private transient int hashCode;
|
|
|
|
/**
|
|
* The arbitrary precision integer (unscaled value) in the internal
|
|
* representation of {@code BigDecimal}.
|
|
*/
|
|
private BigInteger intVal;
|
|
|
|
/**
|
|
* Represent the number of decimal digits in the unscaled value. This
|
|
* precision is calculated the first time, and used in the following calls of
|
|
* method <code>precision()</code>. Note that some call to the private method
|
|
* <code>inplaceRound()</code> could update this field.
|
|
*
|
|
* @see #precision()
|
|
* @see #inplaceRound(MathContext)
|
|
*/
|
|
private transient int precision;
|
|
|
|
private double scale;
|
|
|
|
/**
|
|
* The unscaled integer value (stored in a double) if the number of bits is
|
|
* less than {@link #SMALL_VALUE_BITS}.
|
|
*/
|
|
private transient double smallValue;
|
|
|
|
/**
|
|
* The <code>String</code> representation is cached.
|
|
*/
|
|
private transient String toStringImage;
|
|
|
|
/**
|
|
* Constructs a new {@code BigDecimal} instance from the given big integer
|
|
* {@code val}. The scale of the result is {@code 0}.
|
|
*
|
|
* @param val {@code BigInteger} value to be converted to a {@code BigDecimal}
|
|
* instance.
|
|
*/
|
|
public BigDecimal(BigInteger val) {
|
|
this(val, 0);
|
|
}
|
|
|
|
/**
|
|
* Constructs a new {@code BigDecimal} instance from a given unscaled value
|
|
* {@code unscaledVal} and a given scale. The value of this instance is
|
|
* {@code unscaledVal} 10^(-{@code scale}).
|
|
*
|
|
* @param unscaledVal {@code BigInteger} representing the unscaled value of
|
|
* this {@code BigDecimal} instance.
|
|
* @param scale scale of this {@code BigDecimal} instance.
|
|
* @throws NullPointerException if {@code unscaledVal == null}.
|
|
*/
|
|
public BigDecimal(BigInteger unscaledVal, int scale) {
|
|
if (unscaledVal == null) {
|
|
throw new NullPointerException();
|
|
}
|
|
this.scale = scale;
|
|
setUnscaledValue(unscaledVal);
|
|
}
|
|
|
|
/**
|
|
* Constructs a new {@code BigDecimal} instance from a given unscaled value
|
|
* {@code unscaledVal} and a given scale. The value of this instance is
|
|
* {@code unscaledVal} 10^(-{@code scale}). The result is rounded according to
|
|
* the specified math context.
|
|
*
|
|
* @param unscaledVal {@code BigInteger} representing the unscaled value of
|
|
* this {@code BigDecimal} instance.
|
|
* @param scale scale of this {@code BigDecimal} instance.
|
|
* @param mc rounding mode and precision for the result of this operation.
|
|
* @throws ArithmeticException if {@code mc.precision > 0} and {@code
|
|
* mc.roundingMode == UNNECESSARY} and the new big decimal cannot be
|
|
* represented within the given precision without rounding.
|
|
* @throws NullPointerException if {@code unscaledVal == null}.
|
|
*/
|
|
public BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) {
|
|
this(unscaledVal, scale);
|
|
inplaceRound(mc);
|
|
}
|
|
|
|
/**
|
|
* Constructs a new {@code BigDecimal} instance from the given big integer
|
|
* {@code val}. The scale of the result is {@code 0}.
|
|
*
|
|
* @param val {@code BigInteger} value to be converted to a {@code BigDecimal}
|
|
* instance.
|
|
* @param mc rounding mode and precision for the result of this operation.
|
|
* @throws ArithmeticException if {@code mc.precision > 0} and {@code
|
|
* mc.roundingMode == UNNECESSARY} and the new big decimal cannot be
|
|
* represented within the given precision without rounding.
|
|
*/
|
|
public BigDecimal(BigInteger val, MathContext mc) {
|
|
this(val);
|
|
inplaceRound(mc);
|
|
}
|
|
|
|
/**
|
|
* Constructs a new {@code BigDecimal} instance from a string representation
|
|
* given as a character array.
|
|
*
|
|
* @param in array of characters containing the string representation of this
|
|
* {@code BigDecimal}.
|
|
* @throws NullPointerException if {@code in == null}.
|
|
* @throws NumberFormatException if {@code in} does not contain a valid string
|
|
* representation of a big decimal.
|
|
*/
|
|
public BigDecimal(char[] in) {
|
|
this(in, 0, in.length);
|
|
}
|
|
|
|
/**
|
|
* Constructs a new {@code BigDecimal} instance from a string representation
|
|
* given as a character array.
|
|
*
|
|
* @param in array of characters containing the string representation of this
|
|
* {@code BigDecimal}.
|
|
* @param offset first index to be copied.
|
|
* @param len number of characters to be used.
|
|
* @throws NullPointerException if {@code in == null}.
|
|
* @throws NumberFormatException if {@code offset < 0} or {@code len <= 0} or
|
|
* {@code offset+len-1 < 0} or {@code offset+len-1 >= in.length}.
|
|
* @throws NumberFormatException if in does not contain a valid string
|
|
* representation of a big decimal.
|
|
*/
|
|
public BigDecimal(char[] in, int offset, int len) {
|
|
try {
|
|
initFrom(new String(in, offset, len));
|
|
} catch (StringIndexOutOfBoundsException e) {
|
|
throw new NumberFormatException(e.getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Constructs a new {@code BigDecimal} instance from a string representation
|
|
* given as a character array.
|
|
*
|
|
* @param in array of characters containing the string representation of this
|
|
* {@code BigDecimal}.
|
|
* @param offset first index to be copied.
|
|
* @param len number of characters to be used.
|
|
* @param mc rounding mode and precision for the result of this operation.
|
|
* @throws NullPointerException if {@code in == null}.
|
|
* @throws NumberFormatException if {@code offset < 0} or {@code len <= 0} or
|
|
* {@code offset+len-1 < 0} or {@code offset+len-1 >= in.length}.
|
|
* @throws NumberFormatException if {@code in} does not contain a valid string
|
|
* representation of a big decimal.
|
|
* @throws ArithmeticException if {@code mc.precision > 0} and {@code
|
|
* mc.roundingMode == UNNECESSARY} and the new big decimal cannot be
|
|
* represented within the given precision without rounding.
|
|
*/
|
|
public BigDecimal(char[] in, int offset, int len, MathContext mc) {
|
|
this(in, offset, len);
|
|
inplaceRound(mc);
|
|
}
|
|
|
|
/**
|
|
* Constructs a new {@code BigDecimal} instance from a string representation
|
|
* given as a character array. The result is rounded according to the
|
|
* specified math context.
|
|
*
|
|
* @param in array of characters containing the string representation of this
|
|
* {@code BigDecimal}.
|
|
* @param mc rounding mode and precision for the result of this operation.
|
|
* @throws NullPointerException if {@code in == null}.
|
|
* @throws NumberFormatException if {@code in} does not contain a valid string
|
|
* representation of a big decimal.
|
|
* @throws ArithmeticException if {@code mc.precision > 0} and {@code
|
|
* mc.roundingMode == UNNECESSARY} and the new big decimal cannot be
|
|
* represented within the given precision without rounding.
|
|
*/
|
|
public BigDecimal(char[] in, MathContext mc) {
|
|
this(in, 0, in.length);
|
|
inplaceRound(mc);
|
|
}
|
|
|
|
/**
|
|
* Constructs a new {@code BigDecimal} instance from the given double {@code
|
|
* val}. The scale of the result is 0.
|
|
*
|
|
* @param val double value to be converted to a {@code BigDecimal} instance.
|
|
* @throws NumberFormatException if {@code val} is infinite or a NaN
|
|
*/
|
|
public BigDecimal(double val) {
|
|
if (Double.isInfinite(val) || Double.isNaN(val)) {
|
|
// math.03=Infinity or NaN
|
|
throw new NumberFormatException("Infinite or NaN"); //$NON-NLS-1$
|
|
}
|
|
initFrom(toPrecision(val, 20));
|
|
}
|
|
|
|
/**
|
|
* Constructs a new {@code BigDecimal} instance from the given double {@code
|
|
* val}. The scale of the result is 0. The result is rounded according to the
|
|
* specified math context.
|
|
*
|
|
* @param val double value to be converted to a {@code BigDecimal} instance.
|
|
* @param mc rounding mode and precision for the result of this operation.
|
|
* @throws NumberFormatException if {@code val} is infinite or a NaN
|
|
* @throws ArithmeticException if {@code mc.precision > 0} and {@code
|
|
* mc.roundingMode == UNNECESSARY} and the new big decimal cannot be
|
|
* represented within the given precision without rounding.
|
|
*/
|
|
public BigDecimal(double val, MathContext mc) {
|
|
if (Double.isInfinite(val) || Double.isNaN(val)) {
|
|
// math.03=Infinity or NaN
|
|
throw new NumberFormatException("Infinite or NaN"); //$NON-NLS-1$
|
|
}
|
|
initFrom(toPrecision(val, 20));
|
|
inplaceRound(mc);
|
|
}
|
|
|
|
/**
|
|
* Constructs a new {@code BigDecimal} instance from the given int {@code val}
|
|
* . The scale of the result is 0.
|
|
*
|
|
* @param val int value to be converted to a {@code BigDecimal} instance.
|
|
*/
|
|
public BigDecimal(int val) {
|
|
this(val, 0);
|
|
}
|
|
|
|
/**
|
|
* Constructs a new {@code BigDecimal} instance from the given int {@code val}
|
|
* . The scale of the result is {@code 0}. The result is rounded according to
|
|
* the specified math context.
|
|
*
|
|
* @param val int value to be converted to a {@code BigDecimal} instance.
|
|
* @param mc rounding mode and precision for the result of this operation.
|
|
* @throws ArithmeticException if {@code mc.precision > 0} and {@code
|
|
* c.roundingMode == UNNECESSARY} and the new big decimal cannot be
|
|
* represented within the given precision without rounding.
|
|
*/
|
|
public BigDecimal(int val, MathContext mc) {
|
|
this(val, 0);
|
|
inplaceRound(mc);
|
|
}
|
|
|
|
/**
|
|
* Constructs a new {@code BigDecimal} instance from the given long {@code
|
|
* val}. The scale of the result is {@code 0}.
|
|
*
|
|
* @param val long value to be converted to a {@code BigDecimal} instance.
|
|
*/
|
|
public BigDecimal(long val) {
|
|
this(val, 0);
|
|
}
|
|
|
|
/**
|
|
* Constructs a new {@code BigDecimal} instance from the given long {@code
|
|
* val}. The scale of the result is {@code 0}. The result is rounded according
|
|
* to the specified math context.
|
|
*
|
|
* @param val long value to be converted to a {@code BigDecimal} instance.
|
|
* @param mc rounding mode and precision for the result of this operation.
|
|
* @throws ArithmeticException if {@code mc.precision > 0} and {@code
|
|
* mc.roundingMode == UNNECESSARY} and the new big decimal cannot be
|
|
* represented within the given precision without rounding.
|
|
*/
|
|
public BigDecimal(long val, MathContext mc) {
|
|
this(val);
|
|
inplaceRound(mc);
|
|
}
|
|
|
|
/**
|
|
* Constructs a new {@code BigDecimal} instance from a string representation.
|
|
*
|
|
* @param val string containing the string representation of this {@code
|
|
* BigDecimal}.
|
|
* @throws NumberFormatException if {@code val} does not contain a valid
|
|
* string representation of a big decimal.
|
|
*/
|
|
public BigDecimal(String val) {
|
|
initFrom(val);
|
|
}
|
|
|
|
/**
|
|
* Constructs a new {@code BigDecimal} instance from a string representation.
|
|
* The result is rounded according to the specified math context.
|
|
*
|
|
* @param val string containing the string representation of this {@code
|
|
* BigDecimal}.
|
|
* @param mc rounding mode and precision for the result of this operation.
|
|
* @throws NumberFormatException if {@code val} does not contain a valid
|
|
* string representation of a big decimal.
|
|
* @throws ArithmeticException if {@code mc.precision > 0} and {@code
|
|
* mc.roundingMode == UNNECESSARY} and the new big decimal cannot be
|
|
* represented within the given precision without rounding.
|
|
*/
|
|
public BigDecimal(String val, MathContext mc) {
|
|
this(val.toCharArray(), 0, val.length());
|
|
inplaceRound(mc);
|
|
}
|
|
|
|
private BigDecimal(BigInteger unscaledVal, double scale) {
|
|
if (unscaledVal == null) {
|
|
throw new NullPointerException();
|
|
}
|
|
this.scale = scale;
|
|
setUnscaledValue(unscaledVal);
|
|
}
|
|
|
|
private BigDecimal(double smallValue, double scale) {
|
|
this.smallValue = smallValue;
|
|
this.scale = scale;
|
|
this.bitLength = bitLength(smallValue);
|
|
}
|
|
|
|
private BigDecimal(long smallValue, int scale) {
|
|
this.scale = scale;
|
|
this.bitLength = bitLength(smallValue);
|
|
if (bitLength < SMALL_VALUE_BITS) {
|
|
this.smallValue = smallValue;
|
|
} else {
|
|
this.intVal = BigInteger.valueOf(smallValue);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is the absolute value of
|
|
* {@code this}. The scale of the result is the same as the scale of this.
|
|
*
|
|
* @return {@code abs(this)}
|
|
*/
|
|
public BigDecimal abs() {
|
|
return ((signum() < 0) ? negate() : this);
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is the absolute value of
|
|
* {@code this}. The result is rounded according to the passed context {@code
|
|
* mc}.
|
|
*
|
|
* @param mc rounding mode and precision for the result of this operation.
|
|
* @return {@code abs(this)}
|
|
*/
|
|
public BigDecimal abs(MathContext mc) {
|
|
return round(mc).abs();
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is {@code this + augend}. The
|
|
* scale of the result is the maximum of the scales of the two arguments.
|
|
*
|
|
* @param augend value to be added to {@code this}.
|
|
* @return {@code this + augend}.
|
|
* @throws NullPointerException if {@code augend == null}.
|
|
*/
|
|
public BigDecimal add(BigDecimal augend) {
|
|
double diffScale = this.scale - augend.scale;
|
|
// Fast return when some operand is zero
|
|
if (this.isZero()) {
|
|
if (diffScale <= 0) {
|
|
return augend;
|
|
}
|
|
if (augend.isZero()) {
|
|
return this;
|
|
}
|
|
} else if (augend.isZero()) {
|
|
if (diffScale >= 0) {
|
|
return this;
|
|
}
|
|
}
|
|
// Let be: this = [u1,s1] and augend = [u2,s2]
|
|
if (diffScale == 0) {
|
|
// case s1 == s2: [u1 + u2 , s1]
|
|
if (Math.max(this.bitLength, augend.bitLength) + 1 < SMALL_VALUE_BITS) {
|
|
return valueOf(this.smallValue + augend.smallValue, this.scale);
|
|
}
|
|
return new BigDecimal(this.getUnscaledValue().add(
|
|
augend.getUnscaledValue()), this.scale);
|
|
} else if (diffScale > 0) {
|
|
// case s1 > s2 : [(u1 + u2) * 10 ^ (s1 - s2) , s1]
|
|
return addAndMult10(this, augend, diffScale);
|
|
} else {
|
|
// case s2 > s1 : [(u2 + u1) * 10 ^ (s2 - s1) , s2]
|
|
return addAndMult10(augend, this, -diffScale);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is {@code this + augend}. The
|
|
* result is rounded according to the passed context {@code mc}.
|
|
*
|
|
* @param augend value to be added to {@code this}.
|
|
* @param mc rounding mode and precision for the result of this operation.
|
|
* @return {@code this + augend}.
|
|
* @throws NullPointerException if {@code augend == null} or {@code mc ==
|
|
* null}.
|
|
*/
|
|
public BigDecimal add(BigDecimal augend, MathContext mc) {
|
|
BigDecimal larger; // operand with the largest unscaled value
|
|
BigDecimal smaller; // operand with the smallest unscaled value
|
|
BigInteger tempBI;
|
|
double diffScale = this.scale - augend.scale;
|
|
int largerSignum;
|
|
// Some operand is zero or the precision is infinity
|
|
if ((augend.isZero()) || (this.isZero()) || (mc.getPrecision() == 0)) {
|
|
return add(augend).round(mc);
|
|
}
|
|
// Cases where there is room for optimizations
|
|
if (this.approxPrecision() < diffScale - 1) {
|
|
larger = augend;
|
|
smaller = this;
|
|
} else if (augend.approxPrecision() < -diffScale - 1) {
|
|
larger = this;
|
|
smaller = augend;
|
|
} else {
|
|
// No optimization is done
|
|
return add(augend).round(mc);
|
|
}
|
|
if (mc.getPrecision() >= larger.approxPrecision()) {
|
|
// No optimization is done
|
|
return add(augend).round(mc);
|
|
}
|
|
// Cases where it's unnecessary to add two numbers with very different
|
|
// scales
|
|
largerSignum = larger.signum();
|
|
if (largerSignum == smaller.signum()) {
|
|
tempBI = Multiplication.multiplyByPositiveInt(larger.getUnscaledValue(),
|
|
10).add(BigInteger.valueOf(largerSignum));
|
|
} else {
|
|
tempBI = larger.getUnscaledValue().subtract(
|
|
BigInteger.valueOf(largerSignum));
|
|
tempBI = Multiplication.multiplyByPositiveInt(tempBI, 10).add(
|
|
BigInteger.valueOf(largerSignum * 9));
|
|
}
|
|
// Rounding the improved adding
|
|
larger = new BigDecimal(tempBI, larger.scale + 1);
|
|
return larger.round(mc);
|
|
}
|
|
|
|
/**
|
|
* Returns this {@code BigDecimal} as a byte value if it has no fractional
|
|
* part and if its value fits to the byte range ([-128..127]). If these
|
|
* conditions are not met, an {@code ArithmeticException} is thrown.
|
|
*
|
|
* @return this {@code BigDecimal} as a byte value.
|
|
* @throws ArithmeticException if rounding is necessary or the number doesn't
|
|
* fit in a byte.
|
|
*/
|
|
public byte byteValueExact() {
|
|
return (byte) valueExact(8);
|
|
}
|
|
|
|
/**
|
|
* Compares this {@code BigDecimal} with {@code val}. Returns one of the three
|
|
* values {@code 1}, {@code 0}, or {@code -1}. The method behaves as if
|
|
* {@code this.subtract(val)} is computed. If this difference is > 0 then 1 is
|
|
* returned, if the difference is < 0 then -1 is returned, and if the
|
|
* difference is 0 then 0 is returned. This means, that if two decimal
|
|
* instances are compared which are equal in value but differ in scale, then
|
|
* these two instances are considered as equal.
|
|
*
|
|
* @param val value to be compared with {@code this}.
|
|
* @return {@code 1} if {@code this > val}, {@code -1} if {@code this < val},
|
|
* {@code 0} if {@code this == val}.
|
|
* @throws NullPointerException if {@code val == null}.
|
|
*/
|
|
public int compareTo(BigDecimal val) {
|
|
int thisSign = signum();
|
|
int valueSign = val.signum();
|
|
|
|
if (thisSign == valueSign) {
|
|
if (this.scale == val.scale && this.bitLength < SMALL_VALUE_BITS
|
|
&& val.bitLength < SMALL_VALUE_BITS) {
|
|
return (smallValue < val.smallValue) ? -1
|
|
: (smallValue > val.smallValue) ? 1 : 0;
|
|
}
|
|
double diffScale = this.scale - val.scale;
|
|
double diffPrecision = this.approxPrecision() - val.approxPrecision();
|
|
if (diffPrecision > diffScale + 1) {
|
|
return thisSign;
|
|
} else if (diffPrecision < diffScale - 1) {
|
|
return -thisSign;
|
|
} else {
|
|
// thisSign == val.signum() and diffPrecision is aprox. diffScale
|
|
BigInteger thisUnscaled = this.getUnscaledValue();
|
|
BigInteger valUnscaled = val.getUnscaledValue();
|
|
// If any of both precision is bigger, append zeros to the shorter one
|
|
if (diffScale < 0) {
|
|
thisUnscaled = thisUnscaled.multiply(Multiplication.powerOf10(-diffScale));
|
|
} else if (diffScale > 0) {
|
|
valUnscaled = valUnscaled.multiply(Multiplication.powerOf10(diffScale));
|
|
}
|
|
return thisUnscaled.compareTo(valUnscaled);
|
|
}
|
|
} else if (thisSign < valueSign) {
|
|
return -1;
|
|
} else {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is {@code this / divisor}. The
|
|
* scale of the result is the difference of the scales of {@code this} and
|
|
* {@code divisor}. If the exact result requires more digits, then the scale
|
|
* is adjusted accordingly. For example, {@code 1/128 = 0.0078125} which has a
|
|
* scale of {@code 7} and precision {@code 5}.
|
|
*
|
|
* @param divisor value by which {@code this} is divided.
|
|
* @return {@code this / divisor}.
|
|
* @throws NullPointerException if {@code divisor == null}.
|
|
* @throws ArithmeticException if {@code divisor == 0}.
|
|
* @throws ArithmeticException if the result cannot be represented exactly.
|
|
*/
|
|
public BigDecimal divide(BigDecimal divisor) {
|
|
BigInteger p = this.getUnscaledValue();
|
|
BigInteger q = divisor.getUnscaledValue();
|
|
BigInteger gcd; // greatest common divisor between 'p' and 'q'
|
|
BigInteger quotAndRem[];
|
|
double diffScale = scale - divisor.scale;
|
|
int newScale; // the new scale for final quotient
|
|
int k; // number of factors "2" in 'q'
|
|
int l = 0; // number of factors "5" in 'q'
|
|
int i = 1;
|
|
int lastPow = FIVE_POW.length - 1;
|
|
|
|
if (divisor.isZero()) {
|
|
// math.04=Division by zero
|
|
throw new ArithmeticException("Division by zero"); //$NON-NLS-1$
|
|
}
|
|
if (p.signum() == 0) {
|
|
return zeroScaledBy(diffScale);
|
|
}
|
|
// To divide both by the GCD
|
|
gcd = p.gcd(q);
|
|
p = p.divide(gcd);
|
|
q = q.divide(gcd);
|
|
// To simplify all "2" factors of q, dividing by 2^k
|
|
k = q.getLowestSetBit();
|
|
q = q.shiftRight(k);
|
|
// To simplify all "5" factors of q, dividing by 5^l
|
|
do {
|
|
quotAndRem = q.divideAndRemainder(FIVE_POW[i]);
|
|
if (quotAndRem[1].signum() == 0) {
|
|
l += i;
|
|
if (i < lastPow) {
|
|
i++;
|
|
}
|
|
q = quotAndRem[0];
|
|
} else {
|
|
if (i == 1) {
|
|
break;
|
|
}
|
|
i = 1;
|
|
}
|
|
} while (true);
|
|
// If abs(q) != 1 then the quotient is periodic
|
|
if (!q.abs().equals(BigInteger.ONE)) {
|
|
// math.05=Non-terminating decimal expansion; no exact representable
|
|
// decimal result.
|
|
throw new ArithmeticException(
|
|
"Non-terminating decimal expansion; no exact representable decimal result"); //$NON-NLS-1$
|
|
}
|
|
// The sign of the is fixed and the quotient will be saved in 'p'
|
|
if (q.signum() < 0) {
|
|
p = p.negate();
|
|
}
|
|
// Checking if the new scale is out of range
|
|
newScale = toIntScale(diffScale + Math.max(k, l));
|
|
// k >= 0 and l >= 0 implies that k - l is in the 32-bit range
|
|
i = k - l;
|
|
|
|
p = (i > 0) ? Multiplication.multiplyByFivePow(p, i) : p.shiftLeft(-i);
|
|
return new BigDecimal(p, newScale);
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is {@code this / divisor}. The
|
|
* scale of the result is the scale of {@code this}. If rounding is required
|
|
* to meet the specified scale, then the specified rounding mode {@code
|
|
* roundingMode} is applied.
|
|
*
|
|
* @param divisor value by which {@code this} is divided.
|
|
* @param roundingMode rounding mode to be used to round the result.
|
|
* @return {@code this / divisor} rounded according to the given rounding
|
|
* mode.
|
|
* @throws NullPointerException if {@code divisor == null}.
|
|
* @throws IllegalArgumentException if {@code roundingMode} is not a valid
|
|
* rounding mode.
|
|
* @throws ArithmeticException if {@code divisor == 0}.
|
|
* @throws ArithmeticException if {@code roundingMode == ROUND_UNNECESSARY}
|
|
* and rounding is necessary according to the scale of this.
|
|
*/
|
|
public BigDecimal divide(BigDecimal divisor, int roundingMode) {
|
|
return divide(divisor, (int) scale, RoundingMode.valueOf(roundingMode));
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is {@code this / divisor}. As
|
|
* scale of the result the parameter {@code scale} is used. If rounding is
|
|
* required to meet the specified scale, then the specified rounding mode
|
|
* {@code roundingMode} is applied.
|
|
*
|
|
* @param divisor value by which {@code this} is divided.
|
|
* @param scale the scale of the result returned.
|
|
* @param roundingMode rounding mode to be used to round the result.
|
|
* @return {@code this / divisor} rounded according to the given rounding
|
|
* mode.
|
|
* @throws NullPointerException if {@code divisor == null}.
|
|
* @throws IllegalArgumentException if {@code roundingMode} is not a valid
|
|
* rounding mode.
|
|
* @throws ArithmeticException if {@code divisor == 0}.
|
|
* @throws ArithmeticException if {@code roundingMode == ROUND_UNNECESSARY}
|
|
* and rounding is necessary according to the given scale.
|
|
*/
|
|
public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) {
|
|
return divide(divisor, scale, RoundingMode.valueOf(roundingMode));
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is {@code this / divisor}. As
|
|
* scale of the result the parameter {@code scale} is used. If rounding is
|
|
* required to meet the specified scale, then the specified rounding mode
|
|
* {@code roundingMode} is applied.
|
|
*
|
|
* @param divisor value by which {@code this} is divided.
|
|
* @param scale the scale of the result returned.
|
|
* @param roundingMode rounding mode to be used to round the result.
|
|
* @return {@code this / divisor} rounded according to the given rounding
|
|
* mode.
|
|
* @throws NullPointerException if {@code divisor == null} or {@code
|
|
* roundingMode == null}.
|
|
* @throws ArithmeticException if {@code divisor == 0}.
|
|
* @throws ArithmeticException if {@code roundingMode ==
|
|
* RoundingMode.UNNECESSAR}Y and rounding is necessary according to
|
|
* the given scale and given precision.
|
|
*/
|
|
public BigDecimal divide(BigDecimal divisor, int scale,
|
|
RoundingMode roundingMode) {
|
|
// Let be: this = [u1,s1] and divisor = [u2,s2]
|
|
if (roundingMode == null) {
|
|
throw new NullPointerException();
|
|
}
|
|
if (divisor.isZero()) {
|
|
// math.04=Division by zero
|
|
throw new ArithmeticException("Division by zero"); //$NON-NLS-1$
|
|
}
|
|
|
|
double diffScale = this.scale - divisor.scale - scale;
|
|
if (this.bitLength < SMALL_VALUE_BITS
|
|
&& divisor.bitLength < SMALL_VALUE_BITS) {
|
|
if (diffScale == 0) {
|
|
return dividePrimitiveDoubles(this.smallValue, divisor.smallValue,
|
|
scale, roundingMode);
|
|
} else if (diffScale > 0) {
|
|
if (diffScale < DOUBLE_TEN_POW.length
|
|
&& divisor.bitLength + DOUBLE_TEN_POW_BIT_LENGTH[
|
|
(int) diffScale] < SMALL_VALUE_BITS) {
|
|
return dividePrimitiveDoubles(this.smallValue, divisor.smallValue
|
|
* DOUBLE_TEN_POW[(int) diffScale], scale, roundingMode);
|
|
}
|
|
} else { // diffScale < 0
|
|
if (-diffScale < DOUBLE_TEN_POW.length
|
|
&& this.bitLength + DOUBLE_TEN_POW_BIT_LENGTH[(int) -diffScale]
|
|
< SMALL_VALUE_BITS) {
|
|
return dividePrimitiveDoubles(this.smallValue
|
|
* DOUBLE_TEN_POW[(int) -diffScale], divisor.smallValue, scale,
|
|
roundingMode);
|
|
}
|
|
}
|
|
}
|
|
|
|
BigInteger scaledDividend = this.getUnscaledValue();
|
|
BigInteger scaledDivisor = divisor.getUnscaledValue(); // for scaling of
|
|
// 'u2'
|
|
|
|
if (diffScale > 0) {
|
|
// Multiply 'u2' by: 10^((s1 - s2) - scale)
|
|
scaledDivisor = Multiplication.multiplyByTenPow(scaledDivisor,
|
|
(int) diffScale);
|
|
} else if (diffScale < 0) {
|
|
// Multiply 'u1' by: 10^(scale - (s1 - s2))
|
|
scaledDividend = Multiplication.multiplyByTenPow(scaledDividend,
|
|
(int) -diffScale);
|
|
}
|
|
return divideBigIntegers(scaledDividend, scaledDivisor, scale, roundingMode);
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is {@code this / divisor}. The
|
|
* result is rounded according to the passed context {@code mc}. If the passed
|
|
* math context specifies precision {@code 0}, then this call is equivalent to
|
|
* {@code this.divide(divisor)}.
|
|
*
|
|
* @param divisor value by which {@code this} is divided.
|
|
* @param mc rounding mode and precision for the result of this operation.
|
|
* @return {@code this / divisor}.
|
|
* @throws NullPointerException if {@code divisor == null} or {@code mc ==
|
|
* null}.
|
|
* @throws ArithmeticException if {@code divisor == 0}.
|
|
* @throws ArithmeticException if {@code mc.getRoundingMode() == UNNECESSARY}
|
|
* and rounding is necessary according {@code mc.getPrecision()}.
|
|
*/
|
|
public BigDecimal divide(BigDecimal divisor, MathContext mc) {
|
|
/*
|
|
* Calculating how many zeros must be append to 'dividend' to obtain a
|
|
* quotient with at least 'mc.precision()' digits
|
|
*/
|
|
double traillingZeros = mc.getPrecision() + 2L + divisor.approxPrecision()
|
|
- approxPrecision();
|
|
double diffScale = scale - divisor.scale;
|
|
double newScale = diffScale; // scale of the final quotient
|
|
int compRem; // to compare the remainder
|
|
int i = 1; // index
|
|
int lastPow = TEN_POW.length - 1; // last power of ten
|
|
BigInteger integerQuot; // for temporal results
|
|
BigInteger quotAndRem[] = {getUnscaledValue()};
|
|
// In special cases it reduces the problem to call the dual method
|
|
if ((mc.getPrecision() == 0) || (this.isZero()) || (divisor.isZero())) {
|
|
return this.divide(divisor);
|
|
}
|
|
if (traillingZeros > 0) {
|
|
// To append trailing zeros at end of dividend
|
|
quotAndRem[0] = getUnscaledValue().multiply(
|
|
Multiplication.powerOf10(traillingZeros));
|
|
newScale += traillingZeros;
|
|
}
|
|
quotAndRem = quotAndRem[0].divideAndRemainder(divisor.getUnscaledValue());
|
|
integerQuot = quotAndRem[0];
|
|
// Calculating the exact quotient with at least 'mc.precision()' digits
|
|
if (quotAndRem[1].signum() != 0) {
|
|
// Checking if: 2 * remainder >= divisor ?
|
|
compRem = quotAndRem[1].shiftLeftOneBit().compareTo(
|
|
divisor.getUnscaledValue());
|
|
// quot := quot * 10 + r; with 'r' in {-6,-5,-4, 0,+4,+5,+6}
|
|
integerQuot = integerQuot.multiply(BigInteger.TEN).add(
|
|
BigInteger.valueOf(quotAndRem[0].signum() * (5 + compRem)));
|
|
newScale++;
|
|
} else {
|
|
// To strip trailing zeros until the preferred scale is reached
|
|
while (!integerQuot.testBit(0)) {
|
|
quotAndRem = integerQuot.divideAndRemainder(TEN_POW[i]);
|
|
if ((quotAndRem[1].signum() == 0) && (newScale - i >= diffScale)) {
|
|
newScale -= i;
|
|
if (i < lastPow) {
|
|
i++;
|
|
}
|
|
integerQuot = quotAndRem[0];
|
|
} else {
|
|
if (i == 1) {
|
|
break;
|
|
}
|
|
i = 1;
|
|
}
|
|
}
|
|
}
|
|
// To perform rounding
|
|
return new BigDecimal(integerQuot, toIntScale(newScale), mc);
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is {@code this / divisor}. The
|
|
* scale of the result is the scale of {@code this}. If rounding is required
|
|
* to meet the specified scale, then the specified rounding mode {@code
|
|
* roundingMode} is applied.
|
|
*
|
|
* @param divisor value by which {@code this} is divided.
|
|
* @param roundingMode rounding mode to be used to round the result.
|
|
* @return {@code this / divisor} rounded according to the given rounding
|
|
* mode.
|
|
* @throws NullPointerException if {@code divisor == null} or {@code
|
|
* roundingMode == null}.
|
|
* @throws ArithmeticException if {@code divisor == 0}.
|
|
* @throws ArithmeticException if {@code roundingMode ==
|
|
* RoundingMode.UNNECESSARY} and rounding is necessary according to
|
|
* the scale of this.
|
|
*/
|
|
public BigDecimal divide(BigDecimal divisor, RoundingMode roundingMode) {
|
|
return divide(divisor, (int) scale, roundingMode);
|
|
}
|
|
|
|
/**
|
|
* Returns a {@code BigDecimal} array which contains the integral part of
|
|
* {@code this / divisor} at index 0 and the remainder {@code this % divisor}
|
|
* at index 1. The quotient is rounded down towards zero to the next integer.
|
|
*
|
|
* @param divisor value by which {@code this} is divided.
|
|
* @return {@code [this.divideToIntegralValue(divisor),
|
|
* this.remainder(divisor)]}.
|
|
* @throws NullPointerException if {@code divisor == null}.
|
|
* @throws ArithmeticException if {@code divisor == 0}.
|
|
* @see #divideToIntegralValue
|
|
* @see #remainder
|
|
*/
|
|
public BigDecimal[] divideAndRemainder(BigDecimal divisor) {
|
|
BigDecimal quotAndRem[] = new BigDecimal[2];
|
|
|
|
quotAndRem[0] = this.divideToIntegralValue(divisor);
|
|
quotAndRem[1] = this.subtract(quotAndRem[0].multiply(divisor));
|
|
return quotAndRem;
|
|
}
|
|
|
|
/**
|
|
* Returns a {@code BigDecimal} array which contains the integral part of
|
|
* {@code this / divisor} at index 0 and the remainder {@code this % divisor}
|
|
* at index 1. The quotient is rounded down towards zero to the next integer.
|
|
* The rounding mode passed with the parameter {@code mc} is not considered.
|
|
* But if the precision of {@code mc > 0} and the integral part requires more
|
|
* digits, then an {@code ArithmeticException} is thrown.
|
|
*
|
|
* @param divisor value by which {@code this} is divided.
|
|
* @param mc math context which determines the maximal precision of the
|
|
* result.
|
|
* @return {@code [this.divideToIntegralValue(divisor),
|
|
* this.remainder(divisor)]}.
|
|
* @throws NullPointerException if {@code divisor == null}.
|
|
* @throws ArithmeticException if {@code divisor == 0}.
|
|
* @see #divideToIntegralValue
|
|
* @see #remainder
|
|
*/
|
|
public BigDecimal[] divideAndRemainder(BigDecimal divisor, MathContext mc) {
|
|
BigDecimal quotAndRem[] = new BigDecimal[2];
|
|
|
|
quotAndRem[0] = this.divideToIntegralValue(divisor, mc);
|
|
quotAndRem[1] = this.subtract(quotAndRem[0].multiply(divisor));
|
|
return quotAndRem;
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is the integral part of
|
|
* {@code this / divisor}. The quotient is rounded down towards zero to the
|
|
* next integer. For example, {@code 0.5/0.2 = 2}.
|
|
*
|
|
* @param divisor value by which {@code this} is divided.
|
|
* @return integral part of {@code this / divisor}.
|
|
* @throws NullPointerException if {@code divisor == null}.
|
|
* @throws ArithmeticException if {@code divisor == 0}.
|
|
*/
|
|
public BigDecimal divideToIntegralValue(BigDecimal divisor) {
|
|
BigInteger integralValue; // the integer of result
|
|
BigInteger powerOfTen; // some power of ten
|
|
BigInteger quotAndRem[] = {getUnscaledValue()};
|
|
double newScale = this.scale - divisor.scale;
|
|
double tempScale = 0;
|
|
int i = 1;
|
|
int lastPow = TEN_POW.length - 1;
|
|
|
|
if (divisor.isZero()) {
|
|
// math.04=Division by zero
|
|
throw new ArithmeticException("Division by zero"); //$NON-NLS-1$
|
|
}
|
|
if ((divisor.approxPrecision() + newScale > this.approxPrecision() + 1L)
|
|
|| (this.isZero())) {
|
|
/*
|
|
* If the divisor's integer part is greater than this's integer part, the
|
|
* result must be zero with the appropriate scale
|
|
*/
|
|
integralValue = BigInteger.ZERO;
|
|
} else if (newScale == 0) {
|
|
integralValue = getUnscaledValue().divide(divisor.getUnscaledValue());
|
|
} else if (newScale > 0) {
|
|
powerOfTen = Multiplication.powerOf10(newScale);
|
|
integralValue = getUnscaledValue().divide(
|
|
divisor.getUnscaledValue().multiply(powerOfTen));
|
|
integralValue = integralValue.multiply(powerOfTen);
|
|
} else {
|
|
// (newScale < 0)
|
|
powerOfTen = Multiplication.powerOf10(-newScale);
|
|
integralValue = getUnscaledValue().multiply(powerOfTen).divide(
|
|
divisor.getUnscaledValue());
|
|
// To strip trailing zeros approximating to the preferred scale
|
|
while (!integralValue.testBit(0)) {
|
|
quotAndRem = integralValue.divideAndRemainder(TEN_POW[i]);
|
|
if ((quotAndRem[1].signum() == 0) && (tempScale - i >= newScale)) {
|
|
tempScale -= i;
|
|
if (i < lastPow) {
|
|
i++;
|
|
}
|
|
integralValue = quotAndRem[0];
|
|
} else {
|
|
if (i == 1) {
|
|
break;
|
|
}
|
|
i = 1;
|
|
}
|
|
}
|
|
newScale = tempScale;
|
|
}
|
|
return ((integralValue.signum() == 0) ? zeroScaledBy(newScale)
|
|
: new BigDecimal(integralValue, toIntScale(newScale)));
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is the integral part of
|
|
* {@code this / divisor}. The quotient is rounded down towards zero to the
|
|
* next integer. The rounding mode passed with the parameter {@code mc} is not
|
|
* considered. But if the precision of {@code mc > 0} and the integral part
|
|
* requires more digits, then an {@code ArithmeticException} is thrown.
|
|
*
|
|
* @param divisor value by which {@code this} is divided.
|
|
* @param mc math context which determines the maximal precision of the
|
|
* result.
|
|
* @return integral part of {@code this / divisor}.
|
|
* @throws NullPointerException if {@code divisor == null} or {@code mc ==
|
|
* null}.
|
|
* @throws ArithmeticException if {@code divisor == 0}.
|
|
* @throws ArithmeticException if {@code mc.getPrecision() > 0} and the result
|
|
* requires more digits to be represented.
|
|
*/
|
|
public BigDecimal divideToIntegralValue(BigDecimal divisor, MathContext mc) {
|
|
int mcPrecision = mc.getPrecision();
|
|
int diffPrecision = this.precision() - divisor.precision();
|
|
int lastPow = TEN_POW.length - 1;
|
|
double diffScale = this.scale - divisor.scale;
|
|
double newScale = diffScale;
|
|
double quotPrecision = diffPrecision - diffScale + 1;
|
|
BigInteger quotAndRem[] = new BigInteger[2];
|
|
// In special cases it call the dual method
|
|
if ((mcPrecision == 0) || (this.isZero()) || (divisor.isZero())) {
|
|
return this.divideToIntegralValue(divisor);
|
|
}
|
|
// Let be: this = [u1,s1] and divisor = [u2,s2]
|
|
if (quotPrecision <= 0) {
|
|
quotAndRem[0] = BigInteger.ZERO;
|
|
} else if (diffScale == 0) {
|
|
// CASE s1 == s2: to calculate u1 / u2
|
|
quotAndRem[0] = this.getUnscaledValue().divide(divisor.getUnscaledValue());
|
|
} else if (diffScale > 0) {
|
|
// CASE s1 >= s2: to calculate u1 / (u2 * 10^(s1-s2)
|
|
quotAndRem[0] = this.getUnscaledValue().divide(
|
|
divisor.getUnscaledValue().multiply(
|
|
Multiplication.powerOf10(diffScale)));
|
|
// To chose 10^newScale to get a quotient with at least 'mc.precision()'
|
|
// digits
|
|
newScale = Math.min(diffScale, Math.max(mcPrecision - quotPrecision + 1,
|
|
0));
|
|
// To calculate: (u1 / (u2 * 10^(s1-s2)) * 10^newScale
|
|
quotAndRem[0] = quotAndRem[0].multiply(Multiplication.powerOf10(newScale));
|
|
} else {
|
|
// CASE s2 > s1:
|
|
/*
|
|
* To calculate the minimum power of ten, such that the quotient (u1 *
|
|
* 10^exp) / u2 has at least 'mc.precision()' digits.
|
|
*/
|
|
double exp = Math.min(-diffScale, Math.max((double) mcPrecision
|
|
- diffPrecision, 0));
|
|
double compRemDiv;
|
|
// Let be: (u1 * 10^exp) / u2 = [q,r]
|
|
quotAndRem = this.getUnscaledValue().multiply(
|
|
Multiplication.powerOf10(exp)).divideAndRemainder(
|
|
divisor.getUnscaledValue());
|
|
newScale += exp; // To fix the scale
|
|
exp = -newScale; // The remaining power of ten
|
|
// If after division there is a remainder...
|
|
if ((quotAndRem[1].signum() != 0) && (exp > 0)) {
|
|
// Log10(r) + ((s2 - s1) - exp) > mc.precision ?
|
|
compRemDiv = (new BigDecimal(quotAndRem[1])).precision() + exp
|
|
- divisor.precision();
|
|
if (compRemDiv == 0) {
|
|
// To calculate: (r * 10^exp2) / u2
|
|
quotAndRem[1] = quotAndRem[1].multiply(Multiplication.powerOf10(exp)).divide(
|
|
divisor.getUnscaledValue());
|
|
compRemDiv = Math.abs(quotAndRem[1].signum());
|
|
}
|
|
if (compRemDiv > 0) {
|
|
// The quotient won't fit in 'mc.precision()' digits
|
|
// math.06=Division impossible
|
|
throw new ArithmeticException("Division impossible"); //$NON-NLS-1$
|
|
}
|
|
}
|
|
}
|
|
// Fast return if the quotient is zero
|
|
if (quotAndRem[0].signum() == 0) {
|
|
return zeroScaledBy(diffScale);
|
|
}
|
|
BigInteger strippedBI = quotAndRem[0];
|
|
BigDecimal integralValue = new BigDecimal(quotAndRem[0]);
|
|
int resultPrecision = integralValue.precision();
|
|
int i = 1;
|
|
// To strip trailing zeros until the specified precision is reached
|
|
while (!strippedBI.testBit(0)) {
|
|
quotAndRem = strippedBI.divideAndRemainder(TEN_POW[i]);
|
|
if ((quotAndRem[1].signum() == 0)
|
|
&& ((resultPrecision - i >= mcPrecision) || (newScale - i >= diffScale))) {
|
|
resultPrecision -= i;
|
|
newScale -= i;
|
|
if (i < lastPow) {
|
|
i++;
|
|
}
|
|
strippedBI = quotAndRem[0];
|
|
} else {
|
|
if (i == 1) {
|
|
break;
|
|
}
|
|
i = 1;
|
|
}
|
|
}
|
|
// To check if the result fit in 'mc.precision()' digits
|
|
if (resultPrecision > mcPrecision) {
|
|
// math.06=Division impossible
|
|
throw new ArithmeticException("Division impossible"); //$NON-NLS-1$
|
|
}
|
|
integralValue.scale = toIntScale(newScale);
|
|
integralValue.setUnscaledValue(strippedBI);
|
|
return integralValue;
|
|
}
|
|
|
|
/**
|
|
* Returns this {@code BigDecimal} as a double value. If {@code this} is too
|
|
* big to be represented as an float, then {@code Double.POSITIVE_INFINITY} or
|
|
* {@code Double.NEGATIVE_INFINITY} is returned.
|
|
* <p>
|
|
* Note, that if the unscaled value has more than 53 significant digits, then
|
|
* this decimal cannot be represented exactly in a double variable. In this
|
|
* case the result is rounded.
|
|
* <p>
|
|
* For example, if the instance {@code x1 = new BigDecimal("0.1")} cannot be
|
|
* represented exactly as a double, and thus {@code x1.equals(new
|
|
* BigDecimal(x1.doubleValue())} returns {@code false} for this case.
|
|
* <p>
|
|
* Similarly, if the instance {@code new BigDecimal(9007199254740993L)} is
|
|
* converted to a double, the result is {@code 9.007199254740992E15}.
|
|
* <p>
|
|
*
|
|
* @return this {@code BigDecimal} as a double value.
|
|
*/
|
|
@Override
|
|
public double doubleValue() {
|
|
return Double.parseDouble(this.toString());
|
|
}
|
|
|
|
/**
|
|
* Returns {@code true} if {@code x} is a {@code BigDecimal} instance and if
|
|
* this instance is equal to this big decimal. Two big decimals are equal if
|
|
* their unscaled value and their scale is equal. For example, 1.0
|
|
* (10*10^(-1)) is not equal to 1.00 (100*10^(-2)). Similarly, zero instances
|
|
* are not equal if their scale differs.
|
|
*
|
|
* @param x object to be compared with {@code this}.
|
|
* @return true if {@code x} is a {@code BigDecimal} and {@code this == x}.
|
|
*/
|
|
@Override
|
|
public boolean equals(Object x) {
|
|
if (this == x) {
|
|
return true;
|
|
}
|
|
if (x instanceof BigDecimal) {
|
|
BigDecimal x1 = (BigDecimal) x;
|
|
return x1.scale == scale
|
|
&& (bitLength < SMALL_VALUE_BITS ? (x1.smallValue == smallValue)
|
|
: intVal.equals(x1.intVal));
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Returns this {@code BigDecimal} as a float value. If {@code this} is too
|
|
* big to be represented as an float, then {@code Float.POSITIVE_INFINITY} or
|
|
* {@code Float.NEGATIVE_INFINITY} is returned.
|
|
* <p>
|
|
* Note, that if the unscaled value has more than 24 significant digits, then
|
|
* this decimal cannot be represented exactly in a float variable. In this
|
|
* case the result is rounded.
|
|
* <p>
|
|
* For example, if the instance {@code x1 = new BigDecimal("0.1")} cannot be
|
|
* represented exactly as a float, and thus {@code x1.equals(new
|
|
* BigDecimal(x1.folatValue())} returns {@code false} for this case.
|
|
* <p>
|
|
* Similarly, if the instance {@code new BigDecimal(16777217)} is converted to
|
|
* a float, the result is {@code 1.6777216E}7.
|
|
*
|
|
* @return this {@code BigDecimal} as a float value.
|
|
*/
|
|
@Override
|
|
public float floatValue() {
|
|
/*
|
|
* A similar code like in doubleValue() could be repeated here, but this
|
|
* simple implementation is quite efficient.
|
|
*/
|
|
float floatResult = signum();
|
|
double powerOfTwo = this.bitLength - (scale / LOG10_2);
|
|
if ((powerOfTwo < -149) || (floatResult == 0.0f)) {
|
|
// Cases which 'this' is very small
|
|
floatResult *= 0.0f;
|
|
} else if (powerOfTwo > 129) {
|
|
// Cases which 'this' is very large
|
|
floatResult *= Float.POSITIVE_INFINITY;
|
|
} else {
|
|
floatResult = (float) doubleValue();
|
|
}
|
|
return floatResult;
|
|
}
|
|
|
|
/**
|
|
* Returns a hash code for this {@code BigDecimal}.
|
|
*
|
|
* @return hash code for {@code this}.
|
|
*/
|
|
@Override
|
|
public int hashCode() {
|
|
if (hashCode != 0) {
|
|
return hashCode;
|
|
}
|
|
if (bitLength < SMALL_VALUE_BITS) {
|
|
long longValue = (long) smallValue;
|
|
hashCode = (int) (longValue & 0xffffffff);
|
|
hashCode = 33 * hashCode + (int) ((longValue >> 32) & 0xffffffff);
|
|
hashCode = 17 * hashCode + (int) scale;
|
|
return hashCode;
|
|
}
|
|
hashCode = 17 * intVal.hashCode() + (int) scale;
|
|
return hashCode;
|
|
}
|
|
|
|
/**
|
|
* Returns this {@code BigDecimal} as an int value. Any fractional part is
|
|
* discarded. If the integral part of {@code this} is too big to be
|
|
* represented as an int, then {@code this} % 2^32 is returned.
|
|
*
|
|
* @return this {@code BigDecimal} as a int value.
|
|
*/
|
|
@Override
|
|
public int intValue() {
|
|
/*
|
|
* If scale <= -32 there are at least 32 trailing bits zero in 10^(-scale).
|
|
* If the scale is positive and very large the long value could be zero.
|
|
*/
|
|
return ((scale <= -32) || (scale > approxPrecision()) ? 0
|
|
: toBigInteger().intValue());
|
|
}
|
|
|
|
/**
|
|
* Returns this {@code BigDecimal} as a int value if it has no fractional part
|
|
* and if its value fits to the int range ([-2^{31}..2^{31}-1]). If these
|
|
* conditions are not met, an {@code ArithmeticException} is thrown.
|
|
*
|
|
* @return this {@code BigDecimal} as a int value.
|
|
* @throws ArithmeticException if rounding is necessary or the number doesn't
|
|
* fit in a int.
|
|
*/
|
|
public int intValueExact() {
|
|
return (int) valueExact(32);
|
|
}
|
|
|
|
/**
|
|
* Returns this {@code BigDecimal} as an long value. Any fractional part is
|
|
* discarded. If the integral part of {@code this} is too big to be
|
|
* represented as an long, then {@code this} % 2^64 is returned.
|
|
*
|
|
* @return this {@code BigDecimal} as a long value.
|
|
*/
|
|
@Override
|
|
public long longValue() {
|
|
/*
|
|
* If scale <= -64 there are at least 64 trailing bits zero in 10^(-scale).
|
|
* If the scale is positive and very large the long value could be zero.
|
|
*/
|
|
return ((scale <= -64) || (scale > approxPrecision()) ? 0L
|
|
: toBigInteger().longValue());
|
|
}
|
|
|
|
/**
|
|
* Returns this {@code BigDecimal} as a long value if it has no fractional
|
|
* part and if its value fits to the int range ([-2^{63}..2^{63}-1]). If these
|
|
* conditions are not met, an {@code ArithmeticException} is thrown.
|
|
*
|
|
* @return this {@code BigDecimal} as a long value.
|
|
* @throws ArithmeticException if rounding is necessary or the number doesn't
|
|
* fit in a long.
|
|
*/
|
|
public long longValueExact() {
|
|
return valueExact(64);
|
|
}
|
|
|
|
/**
|
|
* Returns the maximum of this {@code BigDecimal} and {@code val}.
|
|
*
|
|
* @param val value to be used to compute the maximum with this.
|
|
* @return {@code max(this, val}.
|
|
* @throws NullPointerException if {@code val == null}.
|
|
*/
|
|
public BigDecimal max(BigDecimal val) {
|
|
return ((compareTo(val) >= 0) ? this : val);
|
|
}
|
|
|
|
/**
|
|
* Returns the minimum of this {@code BigDecimal} and {@code val}.
|
|
*
|
|
* @param val value to be used to compute the minimum with this.
|
|
* @return {@code min(this, val}.
|
|
* @throws NullPointerException if {@code val == null}.
|
|
*/
|
|
public BigDecimal min(BigDecimal val) {
|
|
return ((compareTo(val) <= 0) ? this : val);
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} instance where the decimal point has been
|
|
* moved {@code n} places to the left. If {@code n < 0} then the decimal point
|
|
* is moved {@code -n} places to the right.
|
|
* <p>
|
|
* The result is obtained by changing its scale. If the scale of the result
|
|
* becomes negative, then its precision is increased such that the scale is
|
|
* zero.
|
|
* <p>
|
|
* Note, that {@code movePointLeft(0)} returns a result which is
|
|
* mathematically equivalent, but which has {@code scale >= 0}.
|
|
*
|
|
* @param n number of placed the decimal point has to be moved.
|
|
* @return {@code this * 10^(-n}).
|
|
*/
|
|
public BigDecimal movePointLeft(int n) {
|
|
return movePoint(scale + n);
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} instance where the decimal point has been
|
|
* moved {@code n} places to the right. If {@code n < 0} then the decimal
|
|
* point is moved {@code -n} places to the left.
|
|
* <p>
|
|
* The result is obtained by changing its scale. If the scale of the result
|
|
* becomes negative, then its precision is increased such that the scale is
|
|
* zero.
|
|
* <p>
|
|
* Note, that {@code movePointRight(0)} returns a result which is
|
|
* mathematically equivalent, but which has scale >= 0.
|
|
*
|
|
* @param n number of placed the decimal point has to be moved.
|
|
* @return {@code this * 10^n}.
|
|
*/
|
|
public BigDecimal movePointRight(int n) {
|
|
return movePoint(scale - n);
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is {@code this * multiplicand}
|
|
* . The scale of the result is the sum of the scales of the two arguments.
|
|
*
|
|
* @param multiplicand value to be multiplied with {@code this}.
|
|
* @return {@code this * multiplicand}.
|
|
* @throws NullPointerException if {@code multiplicand == null}.
|
|
*/
|
|
public BigDecimal multiply(BigDecimal multiplicand) {
|
|
double newScale = this.scale + multiplicand.scale;
|
|
|
|
if ((this.isZero()) || (multiplicand.isZero())) {
|
|
return zeroScaledBy(newScale);
|
|
}
|
|
/*
|
|
* Let be: this = [u1,s1] and multiplicand = [u2,s2] so: this x multiplicand
|
|
* = [ s1 * s2 , s1 + s2 ]
|
|
*/
|
|
if (this.bitLength + multiplicand.bitLength < SMALL_VALUE_BITS) {
|
|
return valueOf(this.smallValue * multiplicand.smallValue,
|
|
toIntScale(newScale));
|
|
}
|
|
return new BigDecimal(this.getUnscaledValue().multiply(
|
|
multiplicand.getUnscaledValue()), toIntScale(newScale));
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is {@code this * multiplicand}
|
|
* . The result is rounded according to the passed context {@code mc}.
|
|
*
|
|
* @param multiplicand value to be multiplied with {@code this}.
|
|
* @param mc rounding mode and precision for the result of this operation.
|
|
* @return {@code this * multiplicand}.
|
|
* @throws NullPointerException if {@code multiplicand == null} or {@code mc
|
|
* == null}.
|
|
*/
|
|
public BigDecimal multiply(BigDecimal multiplicand, MathContext mc) {
|
|
BigDecimal result = multiply(multiplicand);
|
|
|
|
result.inplaceRound(mc);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is the {@code -this}. The
|
|
* scale of the result is the same as the scale of this.
|
|
*
|
|
* @return {@code -this}
|
|
*/
|
|
public BigDecimal negate() {
|
|
if (bitLength < SMALL_VALUE_BITS) {
|
|
return valueOf(-smallValue, scale);
|
|
}
|
|
return new BigDecimal(getUnscaledValue().negate(), scale);
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is the {@code -this}. The
|
|
* result is rounded according to the passed context {@code mc}.
|
|
*
|
|
* @param mc rounding mode and precision for the result of this operation.
|
|
* @return {@code -this}
|
|
*/
|
|
public BigDecimal negate(MathContext mc) {
|
|
return round(mc).negate();
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is {@code +this}. The scale of
|
|
* the result is the same as the scale of this.
|
|
*
|
|
* @return {@code this}
|
|
*/
|
|
public BigDecimal plus() {
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is {@code +this}. The result
|
|
* is rounded according to the passed context {@code mc}.
|
|
*
|
|
* @param mc rounding mode and precision for the result of this operation.
|
|
* @return {@code this}, rounded
|
|
*/
|
|
public BigDecimal plus(MathContext mc) {
|
|
return round(mc);
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is {@code this ^ n}. The scale
|
|
* of the result is {@code n} times the scales of {@code this}.
|
|
* <p>
|
|
* {@code x.pow(0)} returns {@code 1}, even if {@code x == 0}.
|
|
* <p>
|
|
* Implementation Note: The implementation is based on the ANSI standard
|
|
* X3.274-1996 algorithm.
|
|
*
|
|
* @param n exponent to which {@code this} is raised.
|
|
* @return {@code this ^ n}.
|
|
* @throws ArithmeticException if {@code n < 0} or {@code n > 999999999}.
|
|
*/
|
|
public BigDecimal pow(int n) {
|
|
if (n == 0) {
|
|
return ONE;
|
|
}
|
|
if ((n < 0) || (n > 999999999)) {
|
|
// math.07=Invalid Operation
|
|
throw new ArithmeticException("Invalid Operation"); //$NON-NLS-1$
|
|
}
|
|
double newScale = scale * n;
|
|
// Let be: this = [u,s] so: this^n = [u^n, s*n]
|
|
return ((isZero()) ? zeroScaledBy(newScale) : new BigDecimal(
|
|
getUnscaledValue().pow(n), toIntScale(newScale)));
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is {@code this ^ n}. The
|
|
* result is rounded according to the passed context {@code mc}.
|
|
* <p>
|
|
* Implementation Note: The implementation is based on the ANSI standard
|
|
* X3.274-1996 algorithm.
|
|
*
|
|
* @param n exponent to which {@code this} is raised.
|
|
* @param mc rounding mode and precision for the result of this operation.
|
|
* @return {@code this ^ n}.
|
|
* @throws ArithmeticException if {@code n < 0} or {@code n > 999999999}.
|
|
*/
|
|
public BigDecimal pow(int n, MathContext mc) {
|
|
// The ANSI standard X3.274-1996 algorithm
|
|
int m = Math.abs(n);
|
|
int mcPrecision = mc.getPrecision();
|
|
int elength = (int) Math.log10(m) + 1; // decimal digits in 'n'
|
|
int oneBitMask; // mask of bits
|
|
BigDecimal accum; // the single accumulator
|
|
MathContext newPrecision = mc; // MathContext by default
|
|
|
|
// In particular cases, it reduces the problem to call the other 'pow()'
|
|
if ((n == 0) || ((isZero()) && (n > 0))) {
|
|
return pow(n);
|
|
}
|
|
if ((m > 999999999) || ((mcPrecision == 0) && (n < 0))
|
|
|| ((mcPrecision > 0) && (elength > mcPrecision))) {
|
|
// math.07=Invalid Operation
|
|
throw new ArithmeticException("Invalid Operation"); //$NON-NLS-1$
|
|
}
|
|
if (mcPrecision > 0) {
|
|
newPrecision = new MathContext(mcPrecision + elength + 1,
|
|
mc.getRoundingMode());
|
|
}
|
|
// The result is calculated as if 'n' were positive
|
|
accum = round(newPrecision);
|
|
oneBitMask = Integer.highestOneBit(m) >> 1;
|
|
|
|
while (oneBitMask > 0) {
|
|
accum = accum.multiply(accum, newPrecision);
|
|
if ((m & oneBitMask) == oneBitMask) {
|
|
accum = accum.multiply(this, newPrecision);
|
|
}
|
|
oneBitMask >>= 1;
|
|
}
|
|
// If 'n' is negative, the value is divided into 'ONE'
|
|
if (n < 0) {
|
|
accum = ONE.divide(accum, newPrecision);
|
|
}
|
|
// The final value is rounded to the destination precision
|
|
accum.inplaceRound(mc);
|
|
return accum;
|
|
}
|
|
|
|
/**
|
|
* Returns the precision of this {@code BigDecimal}. The precision is the
|
|
* number of decimal digits used to represent this decimal. It is equivalent
|
|
* to the number of digits of the unscaled value. The precision of {@code 0}
|
|
* is {@code 1} (independent of the scale).
|
|
*
|
|
* @return the precision of this {@code BigDecimal}.
|
|
*/
|
|
public int precision() {
|
|
// Checking if the precision already was calculated
|
|
if (precision > 0) {
|
|
return precision;
|
|
}
|
|
double decimalDigits = 1; // the precision to be calculated
|
|
double doubleUnsc = 1; // intVal in 'double'
|
|
|
|
if (bitLength < SMALL_VALUE_BITS) {
|
|
// To calculate the precision for small numbers
|
|
if (bitLength >= 1) {
|
|
doubleUnsc = smallValue;
|
|
}
|
|
decimalDigits += Math.log10(Math.abs(doubleUnsc));
|
|
} else {
|
|
// (bitLength >= 1024)
|
|
/*
|
|
* To calculate the precision for large numbers Note that: 2 ^(bitlength()
|
|
* - 1) <= intVal < 10 ^(precision())
|
|
*/
|
|
decimalDigits += (bitLength - 1) * LOG10_2;
|
|
// If after division the number isn't zero, exists an aditional digit
|
|
if (getUnscaledValue().divide(Multiplication.powerOf10(decimalDigits)).signum() != 0) {
|
|
decimalDigits++;
|
|
}
|
|
}
|
|
precision = (int) decimalDigits;
|
|
return precision;
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is {@code this % divisor}.
|
|
* <p>
|
|
* The remainder is defined as {@code this -
|
|
* this.divideToIntegralValue(divisor) * divisor}.
|
|
*
|
|
* @param divisor value by which {@code this} is divided.
|
|
* @return {@code this % divisor}.
|
|
* @throws NullPointerException if {@code divisor == null}.
|
|
* @throws ArithmeticException if {@code divisor == 0}.
|
|
*/
|
|
public BigDecimal remainder(BigDecimal divisor) {
|
|
return divideAndRemainder(divisor)[1];
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is {@code this % divisor}.
|
|
* <p>
|
|
* The remainder is defined as {@code this -
|
|
* this.divideToIntegralValue(divisor) * divisor}.
|
|
* <p>
|
|
* The specified rounding mode {@code mc} is used for the division only.
|
|
*
|
|
* @param divisor value by which {@code this} is divided.
|
|
* @param mc rounding mode and precision to be used.
|
|
* @return {@code this % divisor}.
|
|
* @throws NullPointerException if {@code divisor == null}.
|
|
* @throws ArithmeticException if {@code divisor == 0}.
|
|
* @throws ArithmeticException if {@code mc.getPrecision() > 0} and the result
|
|
* of {@code this.divideToIntegralValue(divisor, mc)} requires more
|
|
* digits to be represented.
|
|
*/
|
|
public BigDecimal remainder(BigDecimal divisor, MathContext mc) {
|
|
return divideAndRemainder(divisor, mc)[1];
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is {@code this}, rounded
|
|
* according to the passed context {@code mc}.
|
|
* <p>
|
|
* If {@code mc.precision = 0}, then no rounding is performed.
|
|
* <p>
|
|
* If {@code mc.precision > 0} and {@code mc.roundingMode == UNNECESSARY},
|
|
* then an {@code ArithmeticException} is thrown if the result cannot be
|
|
* represented exactly within the given precision.
|
|
*
|
|
* @param mc rounding mode and precision for the result of this operation.
|
|
* @return {@code this} rounded according to the passed context.
|
|
* @throws ArithmeticException if {@code mc.precision > 0} and {@code
|
|
* mc.roundingMode == UNNECESSARY} and this cannot be represented
|
|
* within the given precision.
|
|
*/
|
|
public BigDecimal round(MathContext mc) {
|
|
BigDecimal thisBD = new BigDecimal(getUnscaledValue(), scale);
|
|
|
|
thisBD.inplaceRound(mc);
|
|
return thisBD;
|
|
}
|
|
|
|
/**
|
|
* Returns the scale of this {@code BigDecimal}. The scale is the number of
|
|
* digits behind the decimal point. The value of this {@code BigDecimal} is
|
|
* the unsignedValue * 10^(-scale). If the scale is negative, then this
|
|
* {@code BigDecimal} represents a big integer.
|
|
*
|
|
* @return the scale of this {@code BigDecimal}.
|
|
*/
|
|
public int scale() {
|
|
return (int) scale;
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is {@code this} 10^{@code n}.
|
|
* The scale of the result is {@code this.scale()} - {@code n}. The precision
|
|
* of the result is the precision of {@code this}.
|
|
* <p>
|
|
* This method has the same effect as {@link #movePointRight}, except that the
|
|
* precision is not changed.
|
|
*
|
|
* @param n number of places the decimal point has to be moved.
|
|
* @return {@code this * 10^n}
|
|
*/
|
|
public BigDecimal scaleByPowerOfTen(int n) {
|
|
double newScale = scale - n;
|
|
if (bitLength < SMALL_VALUE_BITS) {
|
|
// Taking care when a 0 is to be scaled
|
|
if (smallValue == 0) {
|
|
return zeroScaledBy(newScale);
|
|
}
|
|
return valueOf(smallValue, toIntScale(newScale));
|
|
}
|
|
return new BigDecimal(getUnscaledValue(), toIntScale(newScale));
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} instance with the specified scale. If the
|
|
* new scale is greater than the old scale, then additional zeros are added to
|
|
* the unscaled value. If the new scale is smaller than the old scale, then
|
|
* trailing zeros are removed. If the trailing digits are not zeros then an
|
|
* ArithmeticException is thrown.
|
|
* <p>
|
|
* If no exception is thrown, then the following equation holds: {@code
|
|
* x.setScale(s).compareTo(x) == 0}.
|
|
*
|
|
* @param newScale scale of the result returned.
|
|
* @return a new {@code BigDecimal} instance with the specified scale.
|
|
* @throws ArithmeticException if rounding would be necessary.
|
|
*/
|
|
public BigDecimal setScale(int newScale) {
|
|
return setScale(newScale, RoundingMode.UNNECESSARY);
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} instance with the specified scale.
|
|
* <p>
|
|
* If the new scale is greater than the old scale, then additional zeros are
|
|
* added to the unscaled value. In this case no rounding is necessary.
|
|
* <p>
|
|
* If the new scale is smaller than the old scale, then trailing digits are
|
|
* removed. If these trailing digits are not zero, then the remaining unscaled
|
|
* value has to be rounded. For this rounding operation the specified rounding
|
|
* mode is used.
|
|
*
|
|
* @param newScale scale of the result returned.
|
|
* @param roundingMode rounding mode to be used to round the result.
|
|
* @return a new {@code BigDecimal} instance with the specified scale.
|
|
* @throws IllegalArgumentException if {@code roundingMode} is not a valid
|
|
* rounding mode.
|
|
* @throws ArithmeticException if {@code roundingMode == ROUND_UNNECESSARY}
|
|
* and rounding is necessary according to the given scale.
|
|
*/
|
|
public BigDecimal setScale(int newScale, int roundingMode) {
|
|
return setScale(newScale, RoundingMode.valueOf(roundingMode));
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} instance with the specified scale.
|
|
* <p>
|
|
* If the new scale is greater than the old scale, then additional zeros are
|
|
* added to the unscaled value. In this case no rounding is necessary.
|
|
* <p>
|
|
* If the new scale is smaller than the old scale, then trailing digits are
|
|
* removed. If these trailing digits are not zero, then the remaining unscaled
|
|
* value has to be rounded. For this rounding operation the specified rounding
|
|
* mode is used.
|
|
*
|
|
* @param newScale scale of the result returned.
|
|
* @param roundingMode rounding mode to be used to round the result.
|
|
* @return a new {@code BigDecimal} instance with the specified scale.
|
|
* @throws NullPointerException if {@code roundingMode == null}.
|
|
* @throws ArithmeticException if {@code roundingMode == ROUND_UNNECESSARY}
|
|
* and rounding is necessary according to the given scale.
|
|
*/
|
|
public BigDecimal setScale(int newScale, RoundingMode roundingMode) {
|
|
if (roundingMode == null) {
|
|
throw new NullPointerException();
|
|
}
|
|
double diffScale = newScale - scale;
|
|
// Let be: 'this' = [u,s]
|
|
if (diffScale == 0) {
|
|
return this;
|
|
}
|
|
if (diffScale > 0) {
|
|
// return [u * 10^(s2 - s), newScale]
|
|
if (diffScale < DOUBLE_TEN_POW.length
|
|
&& (this.bitLength + DOUBLE_TEN_POW_BIT_LENGTH[
|
|
(int) diffScale]) < SMALL_VALUE_BITS) {
|
|
return valueOf(this.smallValue * DOUBLE_TEN_POW[(int) diffScale],
|
|
newScale);
|
|
}
|
|
return new BigDecimal(Multiplication.multiplyByTenPow(getUnscaledValue(),
|
|
(int) diffScale), newScale);
|
|
}
|
|
// diffScale < 0
|
|
// return [u,s] / [1,newScale] with the appropriate scale and rounding
|
|
if (this.bitLength < SMALL_VALUE_BITS
|
|
&& -diffScale < DOUBLE_TEN_POW.length) {
|
|
return dividePrimitiveDoubles(this.smallValue,
|
|
DOUBLE_TEN_POW[(int) -diffScale], newScale, roundingMode);
|
|
}
|
|
return divideBigIntegers(this.getUnscaledValue(),
|
|
Multiplication.powerOf10(-diffScale), newScale, roundingMode);
|
|
}
|
|
|
|
/**
|
|
* Returns this {@code BigDecimal} as a short value if it has no fractional
|
|
* part and if its value fits to the short range ([-2^{15}..2^{15}-1]). If
|
|
* these conditions are not met, an {@code ArithmeticException} is thrown.
|
|
*
|
|
* @return this {@code BigDecimal} as a short value.
|
|
* @throws ArithmeticException if rounding is necessary of the number doesn't
|
|
* fit in a short.
|
|
*/
|
|
public short shortValueExact() {
|
|
return (short) valueExact(16);
|
|
}
|
|
|
|
/**
|
|
* Returns the sign of this {@code BigDecimal}.
|
|
*
|
|
* @return {@code -1} if {@code this < 0}, {@code 0} if {@code this == 0},
|
|
* {@code 1} if {@code this > 0}.
|
|
*/
|
|
public int signum() {
|
|
if (bitLength < SMALL_VALUE_BITS) {
|
|
return this.smallValue < 0 ? -1 : this.smallValue > 0 ? 1 : 0;
|
|
}
|
|
return getUnscaledValue().signum();
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} instance with the same value as {@code
|
|
* this} but with a unscaled value where the trailing zeros have been removed.
|
|
* If the unscaled value of {@code this} has n trailing zeros, then the scale
|
|
* and the precision of the result has been reduced by n.
|
|
*
|
|
* @return a new {@code BigDecimal} instance equivalent to this where the
|
|
* trailing zeros of the unscaled value have been removed.
|
|
*/
|
|
public BigDecimal stripTrailingZeros() {
|
|
int i = 1; // 1 <= i <= 18
|
|
int lastPow = TEN_POW.length - 1;
|
|
double newScale = scale;
|
|
|
|
if (isZero()) {
|
|
return new BigDecimal("0");
|
|
}
|
|
BigInteger strippedBI = getUnscaledValue();
|
|
BigInteger[] quotAndRem;
|
|
|
|
// while the number is even...
|
|
while (!strippedBI.testBit(0)) {
|
|
// To divide by 10^i
|
|
quotAndRem = strippedBI.divideAndRemainder(TEN_POW[i]);
|
|
// To look the remainder
|
|
if (quotAndRem[1].signum() == 0) {
|
|
// To adjust the scale
|
|
newScale -= i;
|
|
if (i < lastPow) {
|
|
// To set to the next power
|
|
i++;
|
|
}
|
|
strippedBI = quotAndRem[0];
|
|
} else {
|
|
if (i == 1) {
|
|
// 'this' has no more trailing zeros
|
|
break;
|
|
}
|
|
// To set to the smallest power of ten
|
|
i = 1;
|
|
}
|
|
}
|
|
return new BigDecimal(strippedBI, toIntScale(newScale));
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is {@code this - subtrahend}.
|
|
* The scale of the result is the maximum of the scales of the two arguments.
|
|
*
|
|
* @param subtrahend value to be subtracted from {@code this}.
|
|
* @return {@code this - subtrahend}.
|
|
* @throws NullPointerException if {@code subtrahend == null}.
|
|
*/
|
|
public BigDecimal subtract(BigDecimal subtrahend) {
|
|
double diffScale = this.scale - subtrahend.scale;
|
|
// Fast return when some operand is zero
|
|
if (this.isZero()) {
|
|
if (diffScale <= 0) {
|
|
return subtrahend.negate();
|
|
}
|
|
if (subtrahend.isZero()) {
|
|
return this;
|
|
}
|
|
} else if (subtrahend.isZero()) {
|
|
if (diffScale >= 0) {
|
|
return this;
|
|
}
|
|
}
|
|
// Let be: this = [u1,s1] and subtrahend = [u2,s2] so:
|
|
if (diffScale == 0) {
|
|
// case s1 = s2 : [u1 - u2 , s1]
|
|
if (Math.max(this.bitLength, subtrahend.bitLength) + 1
|
|
< SMALL_VALUE_BITS) {
|
|
return valueOf(this.smallValue - subtrahend.smallValue, this.scale);
|
|
}
|
|
return new BigDecimal(this.getUnscaledValue().subtract(
|
|
subtrahend.getUnscaledValue()), this.scale);
|
|
} else if (diffScale > 0) {
|
|
// case s1 > s2 : [ u1 - u2 * 10 ^ (s1 - s2) , s1 ]
|
|
if (diffScale < DOUBLE_TEN_POW.length
|
|
&& Math.max(this.bitLength, subtrahend.bitLength
|
|
+ DOUBLE_TEN_POW_BIT_LENGTH[(int) diffScale]) + 1
|
|
< SMALL_VALUE_BITS) {
|
|
return valueOf(this.smallValue - subtrahend.smallValue
|
|
* DOUBLE_TEN_POW[(int) diffScale], this.scale);
|
|
}
|
|
return new BigDecimal(this.getUnscaledValue().subtract(
|
|
Multiplication.multiplyByTenPow(subtrahend.getUnscaledValue(),
|
|
(int) diffScale)), this.scale);
|
|
} else {
|
|
// case s2 > s1 : [ u1 * 10 ^ (s2 - s1) - u2 , s2 ]
|
|
diffScale = -diffScale;
|
|
if (diffScale < DOUBLE_TEN_POW.length
|
|
&& Math.max(this.bitLength
|
|
+ DOUBLE_TEN_POW_BIT_LENGTH[(int) diffScale],
|
|
subtrahend.bitLength) + 1 < SMALL_VALUE_BITS) {
|
|
return valueOf(this.smallValue * DOUBLE_TEN_POW[(int) diffScale]
|
|
- subtrahend.smallValue, subtrahend.scale);
|
|
}
|
|
return new BigDecimal(Multiplication.multiplyByTenPow(
|
|
this.getUnscaledValue(), (int) diffScale).subtract(
|
|
subtrahend.getUnscaledValue()), subtrahend.scale);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns a new {@code BigDecimal} whose value is {@code this - subtrahend}.
|
|
* The result is rounded according to the passed context {@code mc}.
|
|
*
|
|
* @param subtrahend value to be subtracted from {@code this}.
|
|
* @param mc rounding mode and precision for the result of this operation.
|
|
* @return {@code this - subtrahend}.
|
|
* @throws NullPointerException if {@code subtrahend == null} or {@code mc ==
|
|
* null}.
|
|
*/
|
|
public BigDecimal subtract(BigDecimal subtrahend, MathContext mc) {
|
|
double diffScale = subtrahend.scale - this.scale;
|
|
int thisSignum;
|
|
BigDecimal leftOperand; // it will be only the left operand (this)
|
|
BigInteger tempBI;
|
|
// Some operand is zero or the precision is infinity
|
|
if ((subtrahend.isZero()) || (this.isZero()) || (mc.getPrecision() == 0)) {
|
|
return subtract(subtrahend).round(mc);
|
|
}
|
|
// Now: this != 0 and subtrahend != 0
|
|
if (subtrahend.approxPrecision() < diffScale - 1) {
|
|
// Cases where it is unnecessary to subtract two numbers with very
|
|
// different scales
|
|
if (mc.getPrecision() < this.approxPrecision()) {
|
|
thisSignum = this.signum();
|
|
if (thisSignum != subtrahend.signum()) {
|
|
tempBI = Multiplication.multiplyByPositiveInt(
|
|
this.getUnscaledValue(), 10).add(BigInteger.valueOf(thisSignum));
|
|
} else {
|
|
tempBI = this.getUnscaledValue().subtract(
|
|
BigInteger.valueOf(thisSignum));
|
|
tempBI = Multiplication.multiplyByPositiveInt(tempBI, 10).add(
|
|
BigInteger.valueOf(thisSignum * 9));
|
|
}
|
|
// Rounding the improved subtracting
|
|
leftOperand = new BigDecimal(tempBI, this.scale + 1);
|
|
return leftOperand.round(mc);
|
|
}
|
|
}
|
|
// No optimization is done
|
|
return subtract(subtrahend).round(mc);
|
|
}
|
|
|
|
/**
|
|
* Returns this {@code BigDecimal} as a big integer instance. A fractional
|
|
* part is discarded.
|
|
*
|
|
* @return this {@code BigDecimal} as a big integer instance.
|
|
*/
|
|
public BigInteger toBigInteger() {
|
|
if ((scale == 0) || (isZero())) {
|
|
return getUnscaledValue();
|
|
} else if (scale < 0) {
|
|
return getUnscaledValue().multiply(Multiplication.powerOf10(-scale));
|
|
} else {
|
|
// (scale > 0)
|
|
return getUnscaledValue().divide(Multiplication.powerOf10(scale));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns this {@code BigDecimal} as a big integer instance if it has no
|
|
* fractional part. If this {@code BigDecimal} has a fractional part, i.e. if
|
|
* rounding would be necessary, an {@code ArithmeticException} is thrown.
|
|
*
|
|
* @return this {@code BigDecimal} as a big integer value.
|
|
* @throws ArithmeticException if rounding is necessary.
|
|
*/
|
|
public BigInteger toBigIntegerExact() {
|
|
if ((scale == 0) || (isZero())) {
|
|
return getUnscaledValue();
|
|
} else if (scale < 0) {
|
|
return getUnscaledValue().multiply(Multiplication.powerOf10(-scale));
|
|
} else {
|
|
// (scale > 0)
|
|
BigInteger[] integerAndFraction;
|
|
// An optimization before do a heavy division
|
|
if ((scale > approxPrecision())
|
|
|| (scale > getUnscaledValue().getLowestSetBit())) {
|
|
// math.08=Rounding necessary
|
|
throw new ArithmeticException("Rounding necessary"); //$NON-NLS-1$
|
|
}
|
|
integerAndFraction = getUnscaledValue().divideAndRemainder(
|
|
Multiplication.powerOf10(scale));
|
|
if (integerAndFraction[1].signum() != 0) {
|
|
// It exists a non-zero fractional part
|
|
// math.08=Rounding necessary
|
|
throw new ArithmeticException("Rounding necessary"); //$NON-NLS-1$
|
|
}
|
|
return integerAndFraction[0];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns a string representation of this {@code BigDecimal}. This
|
|
* representation always prints all significant digits of this value.
|
|
* <p>
|
|
* If the scale is negative or if {@code scale - precision >= 6} then
|
|
* engineering notation is used. Engineering notation is similar to the
|
|
* scientific notation except that the exponent is made to be a multiple of 3
|
|
* such that the integer part is >= 1 and < 1000.
|
|
*
|
|
* @return a string representation of {@code this} in engineering notation if
|
|
* necessary.
|
|
*/
|
|
public String toEngineeringString() {
|
|
String intString = getUnscaledValue().toString();
|
|
if (scale == 0) {
|
|
return intString;
|
|
}
|
|
int begin = (getUnscaledValue().signum() < 0) ? 2 : 1;
|
|
int end = intString.length();
|
|
double exponent = -scale + end - begin;
|
|
StringBuilder result = new StringBuilder(intString);
|
|
|
|
if ((scale > 0) && (exponent >= -6)) {
|
|
if (exponent >= 0) {
|
|
result.insert(end - (int) scale, '.');
|
|
} else {
|
|
result.insert(begin - 1, "0."); //$NON-NLS-1$
|
|
result.insert(begin + 1, CH_ZEROS, 0, -(int) exponent - 1);
|
|
}
|
|
} else {
|
|
int delta = end - begin;
|
|
int rem = (int) (exponent % 3);
|
|
|
|
if (rem != 0) {
|
|
// adjust exponent so it is a multiple of three
|
|
if (getUnscaledValue().signum() == 0) {
|
|
// zero value
|
|
rem = (rem < 0) ? -rem : 3 - rem;
|
|
exponent += rem;
|
|
} else {
|
|
// nonzero value
|
|
rem = (rem < 0) ? rem + 3 : rem;
|
|
exponent -= rem;
|
|
begin += rem;
|
|
}
|
|
if (delta < 3) {
|
|
for (int i = rem - delta; i > 0; i--) {
|
|
result.insert(end++, '0');
|
|
}
|
|
}
|
|
}
|
|
if (end - begin >= 1) {
|
|
result.insert(begin, '.');
|
|
end++;
|
|
}
|
|
if (exponent != 0) {
|
|
result.insert(end, 'E');
|
|
if (exponent > 0) {
|
|
result.insert(++end, '+');
|
|
}
|
|
result.insert(++end, Long.toString((long) exponent));
|
|
}
|
|
}
|
|
return result.toString();
|
|
}
|
|
|
|
/**
|
|
* Returns a string representation of this {@code BigDecimal}. No scientific
|
|
* notation is used. This methods adds zeros where necessary.
|
|
* <p>
|
|
* If this string representation is used to create a new instance, this
|
|
* instance is generally not identical to {@code this} as the precision
|
|
* changes.
|
|
* <p>
|
|
* {@code x.equals(new BigDecimal(x.toPlainString())} usually returns {@code
|
|
* false}.
|
|
* <p>
|
|
* {@code x.compareTo(new BigDecimal(x.toPlainString())} returns {@code 0}.
|
|
*
|
|
* @return a string representation of {@code this} without exponent part.
|
|
*/
|
|
public String toPlainString() {
|
|
String intStr = getUnscaledValue().toString();
|
|
if ((scale == 0) || ((isZero()) && (scale < 0))) {
|
|
return intStr;
|
|
}
|
|
int begin = (signum() < 0) ? 1 : 0;
|
|
double delta = scale;
|
|
// We take space for all digits, plus a possible decimal point, plus 'scale'
|
|
StringBuilder result = new StringBuilder(intStr.length() + 1
|
|
+ Math.abs((int) scale));
|
|
|
|
if (begin == 1) {
|
|
// If the number is negative, we insert a '-' character at front
|
|
result.append('-');
|
|
}
|
|
if (scale > 0) {
|
|
delta -= (intStr.length() - begin);
|
|
if (delta >= 0) {
|
|
result.append("0."); //$NON-NLS-1$
|
|
// To append zeros after the decimal point
|
|
for (; delta > CH_ZEROS.length; delta -= CH_ZEROS.length) {
|
|
result.append(CH_ZEROS);
|
|
}
|
|
result.append(CH_ZEROS, 0, (int) delta);
|
|
result.append(intStr.substring(begin));
|
|
} else {
|
|
delta = begin - delta;
|
|
result.append(intStr.substring(begin, (int) delta));
|
|
result.append('.');
|
|
result.append(intStr.substring((int) delta));
|
|
}
|
|
} else {
|
|
// (scale <= 0)
|
|
result.append(intStr.substring(begin));
|
|
// To append trailing zeros
|
|
for (; delta < -CH_ZEROS.length; delta += CH_ZEROS.length) {
|
|
result.append(CH_ZEROS);
|
|
}
|
|
result.append(CH_ZEROS, 0, (int) -delta);
|
|
}
|
|
return result.toString();
|
|
}
|
|
|
|
/**
|
|
* Returns a canonical string representation of this {@code BigDecimal}. If
|
|
* necessary, scientific notation is used. This representation always prints
|
|
* all significant digits of this value.
|
|
* <p>
|
|
* If the scale is negative or if {@code scale - precision >= 6} then
|
|
* scientific notation is used.
|
|
*
|
|
* @return a string representation of {@code this} in scientific notation if
|
|
* necessary.
|
|
*/
|
|
@Override
|
|
public String toString() {
|
|
if (toStringImage != null) {
|
|
return toStringImage;
|
|
}
|
|
if (bitLength < 32) {
|
|
// TODO convert to double math dont cast to long :-(
|
|
toStringImage = Conversion.toDecimalScaledString((long) smallValue,
|
|
(int) scale);
|
|
return toStringImage;
|
|
}
|
|
String intString = getUnscaledValue().toString();
|
|
if (scale == 0) {
|
|
return intString;
|
|
}
|
|
int begin = (getUnscaledValue().signum() < 0) ? 2 : 1;
|
|
int end = intString.length();
|
|
double exponent = -scale + end - begin;
|
|
StringBuilder result = new StringBuilder();
|
|
|
|
result.append(intString);
|
|
if ((scale > 0) && (exponent >= -6)) {
|
|
if (exponent >= 0) {
|
|
result.insert(end - (int) scale, '.');
|
|
} else {
|
|
result.insert(begin - 1, "0."); //$NON-NLS-1$
|
|
result.insert(begin + 1, CH_ZEROS, 0, -(int) exponent - 1);
|
|
}
|
|
} else {
|
|
if (end - begin >= 1) {
|
|
result.insert(begin, '.');
|
|
end++;
|
|
}
|
|
result.insert(end, 'E');
|
|
if (exponent > 0) {
|
|
result.insert(++end, '+');
|
|
}
|
|
result.insert(++end, Long.toString((long) exponent));
|
|
}
|
|
toStringImage = result.toString();
|
|
return toStringImage;
|
|
}
|
|
|
|
/**
|
|
* Returns the unit in the last place (ULP) of this {@code BigDecimal}
|
|
* instance. An ULP is the distance to the nearest big decimal with the same
|
|
* precision.
|
|
* <p>
|
|
* The amount of a rounding error in the evaluation of a floating-point
|
|
* operation is often expressed in ULPs. An error of 1 ULP is often seen as a
|
|
* tolerable error.
|
|
* <p>
|
|
* For class {@code BigDecimal}, the ULP of a number is simply 10^(-scale).
|
|
* <p>
|
|
* For example, {@code new BigDecimal(0.1).ulp()} returns {@code 1E-55}.
|
|
*
|
|
* @return unit in the last place (ULP) of this {@code BigDecimal} instance.
|
|
*/
|
|
public BigDecimal ulp() {
|
|
return valueOf(1, scale);
|
|
}
|
|
|
|
/**
|
|
* Returns the unscaled value (mantissa) of this {@code BigDecimal} instance
|
|
* as a {@code BigInteger}. The unscaled value can be computed as {@code this}
|
|
* 10^(scale).
|
|
*
|
|
* @return unscaled value (this * 10^(scale)).
|
|
*/
|
|
public BigInteger unscaledValue() {
|
|
return getUnscaledValue();
|
|
}
|
|
|
|
/**
|
|
* If the precision already was calculated it returns that value, otherwise it
|
|
* calculates a very good approximation efficiently . Note that this value
|
|
* will be {@code precision()} or {@code precision()-1} in the worst case.
|
|
*
|
|
* @return an approximation of {@code precision()} value
|
|
*/
|
|
private double approxPrecision() {
|
|
return (precision > 0) ? precision
|
|
: Math.floor((this.bitLength - 1) * LOG10_2) + 1;
|
|
}
|
|
|
|
private BigInteger getUnscaledValue() {
|
|
if (intVal == null) {
|
|
intVal = BigInteger.valueOf(smallValue);
|
|
}
|
|
return intVal;
|
|
}
|
|
|
|
private void initFrom(String val) {
|
|
int begin = 0; // first index to be copied
|
|
int offset = 0;
|
|
int last = val.length(); // one past the last index to be copied
|
|
String scaleString = null; // buffer for scale
|
|
StringBuilder unscaledBuffer; // buffer for unscaled value
|
|
|
|
unscaledBuffer = new StringBuilder(val.length());
|
|
// To skip a possible '+' symbol
|
|
if ((offset < last) && (val.charAt(offset) == '+')) {
|
|
offset++;
|
|
begin++;
|
|
|
|
// Fail if the next character is another sign.
|
|
if ((offset < last)
|
|
&& (val.charAt(offset) == '+' || val.charAt(offset) == '-')) {
|
|
throw new NumberFormatException("For input string: \"" + val + "\"");
|
|
}
|
|
}
|
|
int counter = 0;
|
|
boolean wasNonZero = false;
|
|
// Accumulating all digits until a possible decimal point
|
|
for (; (offset < last) && (val.charAt(offset) != '.')
|
|
&& (val.charAt(offset) != 'e') && (val.charAt(offset) != 'E'); offset++) {
|
|
if (!wasNonZero) {
|
|
if (val.charAt(offset) == '0') {
|
|
counter++;
|
|
} else {
|
|
wasNonZero = true;
|
|
}
|
|
}
|
|
}
|
|
unscaledBuffer.append(val, begin, offset);
|
|
// A decimal point was found
|
|
if ((offset < last) && (val.charAt(offset) == '.')) {
|
|
offset++;
|
|
// Accumulating all digits until a possible exponent
|
|
begin = offset;
|
|
for (; (offset < last) && (val.charAt(offset) != 'e')
|
|
&& (val.charAt(offset) != 'E'); offset++) {
|
|
if (!wasNonZero) {
|
|
if (val.charAt(offset) == '0') {
|
|
counter++;
|
|
} else {
|
|
wasNonZero = true;
|
|
}
|
|
}
|
|
}
|
|
scale = offset - begin;
|
|
unscaledBuffer.append(val, begin, offset);
|
|
} else {
|
|
scale = 0;
|
|
}
|
|
// An exponent was found
|
|
if ((offset < last)
|
|
&& ((val.charAt(offset) == 'e') || (val.charAt(offset) == 'E'))) {
|
|
offset++;
|
|
// Checking for a possible sign of scale
|
|
begin = offset;
|
|
if ((offset < last) && (val.charAt(offset) == '+')) {
|
|
offset++;
|
|
if ((offset < last) && (val.charAt(offset) != '-')) {
|
|
begin++;
|
|
}
|
|
}
|
|
// Accumulating all remaining digits
|
|
scaleString = val.substring(begin, last);
|
|
// Checking if the scale is defined
|
|
scale = scale - Integer.parseInt(scaleString);
|
|
if (scale != (int) scale) {
|
|
// math.02=Scale out of range.
|
|
throw new NumberFormatException("Scale out of range."); //$NON-NLS-1$
|
|
}
|
|
}
|
|
// Parsing the unscaled value
|
|
String unscaled = unscaledBuffer.toString();
|
|
if (unscaled.length() < 16) {
|
|
smallValue = parseUnscaled(unscaled);
|
|
if (Double.isNaN(smallValue)) {
|
|
throw new NumberFormatException("For input string: \"" + val + "\"");
|
|
}
|
|
bitLength = bitLength(smallValue);
|
|
} else {
|
|
setUnscaledValue(new BigInteger(unscaled));
|
|
}
|
|
precision = unscaledBuffer.length() - counter;
|
|
// Don't count leading zeros in the precision
|
|
for (int i = 0; i < unscaledBuffer.length(); ++i) {
|
|
char ch = unscaledBuffer.charAt(i);
|
|
if (ch != '-' && ch != '0') {
|
|
break;
|
|
}
|
|
--precision;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* It does all rounding work of the public method {@code round(MathContext)},
|
|
* performing an inplace rounding without creating a new object.
|
|
*
|
|
* @param mc the {@code MathContext} for perform the rounding.
|
|
* @see #round(MathContext)
|
|
*/
|
|
private void inplaceRound(MathContext mc) {
|
|
int mcPrecision = mc.getPrecision();
|
|
if (approxPrecision() - mcPrecision < 0 || mcPrecision == 0) {
|
|
return;
|
|
}
|
|
int discardedPrecision = precision() - mcPrecision;
|
|
// If no rounding is necessary it returns immediately
|
|
if ((discardedPrecision <= 0)) {
|
|
return;
|
|
}
|
|
// When the number is small perform an efficient rounding
|
|
if (this.bitLength < SMALL_VALUE_BITS) {
|
|
smallRound(mc, discardedPrecision);
|
|
return;
|
|
}
|
|
// Getting the integer part and the discarded fraction
|
|
BigInteger sizeOfFraction = Multiplication.powerOf10(discardedPrecision);
|
|
BigInteger[] integerAndFraction = getUnscaledValue().divideAndRemainder(
|
|
sizeOfFraction);
|
|
double newScale = scale - discardedPrecision;
|
|
int compRem;
|
|
BigDecimal tempBD;
|
|
// If the discarded fraction is non-zero, perform rounding
|
|
if (integerAndFraction[1].signum() != 0) {
|
|
// To check if the discarded fraction >= 0.5
|
|
compRem = (integerAndFraction[1].abs().shiftLeftOneBit().compareTo(sizeOfFraction));
|
|
// To look if there is a carry
|
|
compRem = roundingBehavior(integerAndFraction[0].testBit(0) ? 1 : 0,
|
|
integerAndFraction[1].signum() * (5 + compRem), mc.getRoundingMode());
|
|
if (compRem != 0) {
|
|
integerAndFraction[0] = integerAndFraction[0].add(BigInteger.valueOf(compRem));
|
|
}
|
|
tempBD = new BigDecimal(integerAndFraction[0]);
|
|
// If after to add the increment the precision changed, we normalize the
|
|
// size
|
|
if (tempBD.precision() > mcPrecision) {
|
|
integerAndFraction[0] = integerAndFraction[0].divide(BigInteger.TEN);
|
|
newScale--;
|
|
}
|
|
}
|
|
// To update all internal fields
|
|
scale = toIntScale(newScale);
|
|
precision = mcPrecision;
|
|
setUnscaledValue(integerAndFraction[0]);
|
|
}
|
|
|
|
private boolean isZero() {
|
|
return bitLength == 0 && this.smallValue != -1;
|
|
}
|
|
|
|
private BigDecimal movePoint(double newScale) {
|
|
if (isZero()) {
|
|
return zeroScaledBy(Math.max(newScale, 0));
|
|
}
|
|
/*
|
|
* When: 'n'== Integer.MIN_VALUE isn't possible to call to
|
|
* movePointRight(-n) since -Integer.MIN_VALUE == Integer.MIN_VALUE
|
|
*/
|
|
if (newScale >= 0) {
|
|
if (bitLength < SMALL_VALUE_BITS) {
|
|
return valueOf(smallValue, toIntScale(newScale));
|
|
}
|
|
return new BigDecimal(getUnscaledValue(), toIntScale(newScale));
|
|
}
|
|
if (-newScale < DOUBLE_TEN_POW.length
|
|
&& bitLength + DOUBLE_TEN_POW_BIT_LENGTH[(int) -newScale]
|
|
< SMALL_VALUE_BITS) {
|
|
return valueOf(smallValue * DOUBLE_TEN_POW[(int) -newScale], 0);
|
|
}
|
|
return new BigDecimal(Multiplication.multiplyByTenPow(getUnscaledValue(),
|
|
(int) -newScale), 0);
|
|
}
|
|
|
|
private void setUnscaledValue(BigInteger unscaledValue) {
|
|
this.intVal = unscaledValue;
|
|
this.bitLength = unscaledValue.bitLength();
|
|
if (this.bitLength < SMALL_VALUE_BITS) {
|
|
this.smallValue = unscaledValue.longValue();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This method implements an efficient rounding for numbers which unscaled
|
|
* value fits in the type {@code long}.
|
|
*
|
|
* @param mc the context to use
|
|
* @param discardedPrecision the number of decimal digits that are discarded
|
|
* @see #round(MathContext)
|
|
*/
|
|
private void smallRound(MathContext mc, int discardedPrecision) {
|
|
long sizeOfFraction = (long) DOUBLE_TEN_POW[discardedPrecision];
|
|
long newScale = (long) scale - discardedPrecision;
|
|
long unscaledVal = (long) smallValue; // TODO convert to double math dont
|
|
// use longs
|
|
// Getting the integer part and the discarded fraction
|
|
long integer = unscaledVal / sizeOfFraction;
|
|
long fraction = unscaledVal % sizeOfFraction;
|
|
int compRem;
|
|
// If the discarded fraction is non-zero perform rounding
|
|
if (fraction != 0) {
|
|
// To check if the discarded fraction >= 0.5
|
|
compRem = longCompareTo(Math.abs(fraction) << 1, sizeOfFraction);
|
|
// To look if there is a carry
|
|
integer += roundingBehavior(((int) integer) & 1, Long.signum(fraction)
|
|
* (5 + compRem), mc.getRoundingMode());
|
|
// If after to add the increment the precision changed, we normalize the
|
|
// size
|
|
if (Math.log10(Math.abs(integer)) >= mc.getPrecision()) {
|
|
integer /= 10;
|
|
newScale--;
|
|
}
|
|
}
|
|
// To update all internal fields
|
|
scale = toIntScale(newScale);
|
|
precision = mc.getPrecision();
|
|
smallValue = integer;
|
|
bitLength = bitLength(integer);
|
|
intVal = null;
|
|
}
|
|
|
|
/**
|
|
* If {@code intVal} has a fractional part throws an exception, otherwise it
|
|
* counts the number of bits of value and checks if it's out of the range of
|
|
* the primitive type. If the number fits in the primitive type returns this
|
|
* number as {@code long}, otherwise throws an exception.
|
|
*
|
|
* @param bitLengthOfType number of bits of the type whose value will be
|
|
* calculated exactly
|
|
* @return the exact value of the integer part of {@code BigDecimal} when is
|
|
* possible
|
|
* @throws ArithmeticException when rounding is necessary or the number don't
|
|
* fit in the primitive type
|
|
*/
|
|
private long valueExact(int bitLengthOfType) {
|
|
BigInteger bigInteger = toBigIntegerExact();
|
|
|
|
if (bigInteger.bitLength() < bitLengthOfType) {
|
|
// It fits in the primitive type
|
|
return bigInteger.longValue();
|
|
}
|
|
// math.08=Rounding necessary
|
|
throw new ArithmeticException("Rounding necessary"); //$NON-NLS-1$
|
|
}
|
|
}
|