com.ibm.icu.math.BigDecimal Maven / Gradle / Ivy
Show all versions of icu4j Show documentation
// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
/* Generated from 'BigDecimal.nrx' 8 Sep 2000 11:10:50 [v2.00] */
/* Options: Binary Comments Crossref Format Java Logo Strictargs Strictcase Trace2 Verbose3 */
package com.ibm.icu.math;
import java.math.BigInteger;
import com.ibm.icu.lang.UCharacter;
/* ------------------------------------------------------------------ */
/* BigDecimal -- Decimal arithmetic for Java */
/* ------------------------------------------------------------------ */
/* Copyright IBM Corporation, 1996-2016. All Rights Reserved. */
/* */
/* The BigDecimal class provides immutable arbitrary-precision */
/* floating point (including integer) decimal numbers. */
/* */
/* As the numbers are decimal, there is an exact correspondence */
/* between an instance of a BigDecimal object and its String */
/* representation; the BigDecimal class provides direct conversions */
/* to and from String and character array objects, and well as */
/* conversions to and from the Java primitive types (which may not */
/* be exact). */
/* ------------------------------------------------------------------ */
/* Notes: */
/* */
/* 1. A BigDecimal object is never changed in value once constructed; */
/* this avoids the need for locking. Note in particular that the */
/* mantissa array may be shared between many BigDecimal objects, */
/* so that once exposed it must not be altered. */
/* */
/* 2. This class looks at MathContext class fields directly (for */
/* performance). It must not and does not change them. */
/* */
/* 3. Exponent checking is delayed until finish(), as we know */
/* intermediate calculations cannot cause 31-bit overflow. */
/* [This assertion depends on MAX_DIGITS in MathContext.] */
/* */
/* 4. Comments for the public API now follow the javadoc conventions. */
/* The NetRexx -comments option is used to pass these comments */
/* through to the generated Java code (with -format, if desired). */
/* */
/* 5. System.arraycopy is faster than explicit loop as follows */
/* Mean length 4: equal */
/* Mean length 8: x2 */
/* Mean length 16: x3 */
/* Mean length 24: x4 */
/* From prior experience, we expect mean length a little below 8, */
/* but arraycopy is still the one to use, in general, until later */
/* measurements suggest otherwise. */
/* */
/* 6. 'DMSRCN' referred to below is the original (1981) IBM S/370 */
/* assembler code implementation of the algorithms below; it is */
/* now called IXXRCN and is available with the OS/390 and VM/ESA */
/* operating systems. */
/* ------------------------------------------------------------------ */
/* Change History: */
/* 1997.09.02 Initial version (derived from netrexx.lang classes) */
/* 1997.09.12 Add lostDigits checking */
/* 1997.10.06 Change mantissa to a byte array */
/* 1997.11.22 Rework power [did not prepare arguments, etc.] */
/* 1997.12.13 multiply did not prepare arguments */
/* 1997.12.14 add did not prepare and align arguments correctly */
/* 1998.05.02 0.07 packaging changes suggested by Sun and Oracle */
/* 1998.05.21 adjust remainder operator finalization */
/* 1998.06.04 rework to pass MathContext to finish() and round() */
/* 1998.06.06 change format to use round(); support rounding modes */
/* 1998.06.25 rename to BigDecimal and begin merge */
/* zero can now have trailing zeros (i.e., exp\=0) */
/* 1998.06.28 new methods: movePointXxxx, scale, toBigInteger */
/* unscaledValue, valueof */
/* 1998.07.01 improve byteaddsub to allow array reuse, etc. */
/* 1998.07.01 make null testing explicit to avoid JIT bug [Win32] */
/* 1998.07.07 scaled division [divide(BigDecimal, int, int)] */
/* 1998.07.08 setScale, faster equals */
/* 1998.07.11 allow 1E6 (no sign) ; new double/float conversion */
/* 1998.10.12 change package to com.ibm.icu.math */
/* 1998.12.14 power operator no longer rounds RHS [to match ANSI] */
/* add toBigDecimal() and BigDecimal(java.math.BigDecimal) */
/* 1998.12.29 improve byteaddsub by using table lookup */
/* 1999.02.04 lostdigits=0 behaviour rounds instead of digits+1 guard */
/* 1999.02.05 cleaner code for BigDecimal(char[]) */
/* 1999.02.06 add javadoc comments */
/* 1999.02.11 format() changed from 7 to 2 method form */
/* 1999.03.05 null pointer checking is no longer explicit */
/* 1999.03.05 simplify; changes from discussion with J. Bloch: */
/* null no longer permitted for MathContext; drop boolean, */
/* byte, char, float, short constructor, deprecate double */
/* constructor, no blanks in string constructor, add */
/* offset and length version of char[] constructor; */
/* add valueOf(double); drop booleanValue, charValue; */
/* add ...Exact versions of remaining convertors */
/* 1999.03.13 add toBigIntegerExact */
/* 1999.03.13 1.00 release to IBM Centre for Java Technology */
/* 1999.05.27 1.01 correct 0-0.2 bug under scaled arithmetic */
/* 1999.06.29 1.02 constructors should not allow exponent > 9 digits */
/* 1999.07.03 1.03 lost digits should not be checked if digits=0 */
/* 1999.07.06 lost digits Exception message changed */
/* 1999.07.10 1.04 more work on 0-0.2 (scaled arithmetic) */
/* 1999.07.17 improve messages from pow method */
/* 1999.08.08 performance tweaks */
/* 1999.08.15 fastpath in multiply */
/* 1999.11.05 1.05 fix problem in intValueExact [e.g., 5555555555] */
/* 1999.12.22 1.06 remove multiply fastpath, and improve performance */
/* 2000.01.01 copyright update [Y2K has arrived] */
/* 2000.06.18 1.08 no longer deprecate BigDecimal(double) */
/* ------------------------------------------------------------------ */
/**
* The BigDecimal
class implements immutable arbitrary-precision decimal numbers. The methods of the
* BigDecimal
class provide operations for fixed and floating point arithmetic, comparison, format
* conversions, and hashing.
*
* As the numbers are decimal, there is an exact correspondence between an instance of a BigDecimal
object
* and its String
representation; the BigDecimal
class provides direct conversions to and from
* String
and character array (char[]
) objects, as well as conversions to and from the Java
* primitive types (which may not be exact) and BigInteger
.
*
* In the descriptions of constructors and methods in this documentation, the value of a BigDecimal
number
* object is shown as the result of invoking the toString()
method on the object. The internal
* representation of a decimal number is neither defined nor exposed, and is not permitted to affect the result of any
* operation.
*
* The floating point arithmetic provided by this class is defined by the ANSI X3.274-1996 standard, and is also
* documented at http://www2.hursley.ibm.com/decimal
* [This URL will change.]
*
*
Operator methods
*
* Operations on BigDecimal
numbers are controlled by a {@link MathContext} object, which provides the
* context (precision and other information) for the operation. Methods that can take a MathContext
* parameter implement the standard arithmetic operators for BigDecimal
objects and are known as
* operator methods. The default settings provided by the constant {@link MathContext#DEFAULT} (digits=9,
* form=SCIENTIFIC, lostDigits=false, roundingMode=ROUND_HALF_UP
) perform general-purpose floating point
* arithmetic to nine digits of precision. The MathContext
parameter must not be null
.
*
* Each operator method also has a version provided which does not take a MathContext
parameter. For this
* version of each method, the context settings used are digits=0,
* form=PLAIN, lostDigits=false, roundingMode=ROUND_HALF_UP
; these settings perform fixed point arithmetic with
* unlimited precision, as defined for the original BigDecimal class in Java 1.1 and Java 1.2.
*
* For monadic operators, only the optional MathContext
parameter is present; the operation acts upon the
* current object.
*
* For dyadic operators, a BigDecimal
parameter is always present; it must not be null
. The
* operation acts with the current object being the left-hand operand and the BigDecimal
parameter being
* the right-hand operand.
*
* For example, adding two BigDecimal
objects referred to by the names award
and
* extra
could be written as any of:
*
*
* award.add(extra)
*
award.add(extra, MathContext.DEFAULT)
*
award.add(extra, acontext)
*
*
* (where acontext
is a MathContext
object), which would return a BigDecimal
* object whose value is the result of adding award
and extra
under the appropriate context
* settings.
*
* When a BigDecimal
operator method is used, a set of rules define what the result will be (and, by
* implication, how the result would be represented as a character string). These rules are defined in the BigDecimal
* arithmetic documentation (see the URL above), but in summary:
*
* - Results are normally calculated with up to some maximum number of significant digits. For example, if the
*
MathContext
parameter for an operation were MathContext.DEFAULT
then the result would be
* rounded to 9 digits; the division of 2 by 3 would then result in 0.666666667.
* You can change the default of 9 significant digits by providing the method with a suitable MathContext
* object. This lets you calculate using as many digits as you need -- thousands, if necessary. Fixed point (scaled)
* arithmetic is indicated by using a digits
setting of 0 (or omitting the MathContext
* parameter).
* Similarly, you can change the algorithm used for rounding from the default "classic" algorithm.
* -
* In standard arithmetic (that is, when the
form
setting is not PLAIN
), a zero result is
* always expressed as the single digit '0'
(that is, with no sign, decimal point, or exponent part).
* -
* Except for the division and power operators in standard arithmetic, trailing zeros are preserved (this is in contrast
* to binary floating point operations and most electronic calculators, which lose the information about trailing zeros
* in the fractional part of results).
* So, for example:
*
*
* new BigDecimal("2.40").add( new BigDecimal("2")) => "4.40"
*
new BigDecimal("2.40").subtract(new BigDecimal("2")) => "0.40"
*
new BigDecimal("2.40").multiply(new BigDecimal("2")) => "4.80"
*
new BigDecimal("2.40").divide( new BigDecimal("2"), def) => "1.2"
*
*
* where the value on the right of the =>
would be the result of the operation, expressed as a
* String
, and def
(in this and following examples) refers to MathContext.DEFAULT
* ). This preservation of trailing zeros is desirable for most calculations (including financial calculations). If
* necessary, trailing zeros may be easily removed using division by 1.
*
-
* In standard arithmetic, exponential form is used for a result depending on its value and the current setting of
*
digits
(the default is 9 digits). If the number of places needed before the decimal point exceeds the
* digits
setting, or the absolute value of the number is less than 0.000001
, then the number
* will be expressed in exponential notation; thus
*
*
* new BigDecimal("1e+6").multiply(new BigDecimal("1e+6"), def)
*
*
* results in 1E+12
instead of 1000000000000
, and
*
*
* new BigDecimal("1").divide(new BigDecimal("3E+10"), def)
*
*
* results in 3.33333333E-11
instead of 0.0000000000333333333
.
*
* The form of the exponential notation (scientific or engineering) is determined by the form
setting.
*
*
* The names of methods in this class follow the conventions established by java.lang.Number
,
* java.math.BigInteger
, and java.math.BigDecimal
in Java 1.1 and Java 1.2.
*
* @see MathContext
* @author Mike Cowlishaw
* @stable ICU 2.0
*/
public class BigDecimal extends java.lang.Number implements java.io.Serializable, java.lang.Comparable {
// private static final java.lang.String $0="BigDecimal.nrx";
/* ----- Constants ----- */
/* properties constant public */// useful to others
/**
* The BigDecimal
constant "0".
*
* @see #ONE
* @see #TEN
* @stable ICU 2.0
*/
public static final com.ibm.icu.math.BigDecimal ZERO = new com.ibm.icu.math.BigDecimal((long) 0); // use long as we
// want the int
// constructor
// .. to be able to use this, for speed
/**
* The BigDecimal
constant "1".
*
* @see #TEN
* @see #ZERO
* @stable ICU 2.0
*/
public static final com.ibm.icu.math.BigDecimal ONE = new com.ibm.icu.math.BigDecimal((long) 1); // use long as we
// want the int
// constructor
// .. to be able to use this, for speed
/**
* The BigDecimal
constant "10".
*
* @see #ONE
* @see #ZERO
* @stable ICU 2.0
*/
public static final com.ibm.icu.math.BigDecimal TEN = new com.ibm.icu.math.BigDecimal(10);
// the rounding modes (copied here for upwards compatibility)
/**
* Rounding mode to round to a more positive number.
*
* @see MathContext#ROUND_CEILING
* @stable ICU 2.0
*/
public static final int ROUND_CEILING = com.ibm.icu.math.MathContext.ROUND_CEILING;
/**
* Rounding mode to round towards zero.
*
* @see MathContext#ROUND_DOWN
* @stable ICU 2.0
*/
public static final int ROUND_DOWN = com.ibm.icu.math.MathContext.ROUND_DOWN;
/**
* Rounding mode to round to a more negative number.
*
* @see MathContext#ROUND_FLOOR
* @stable ICU 2.0
*/
public static final int ROUND_FLOOR = com.ibm.icu.math.MathContext.ROUND_FLOOR;
/**
* Rounding mode to round to nearest neighbor, where an equidistant value is rounded down.
*
* @see MathContext#ROUND_HALF_DOWN
* @stable ICU 2.0
*/
public static final int ROUND_HALF_DOWN = com.ibm.icu.math.MathContext.ROUND_HALF_DOWN;
/**
* Rounding mode to round to nearest neighbor, where an equidistant value is rounded to the nearest even neighbor.
*
* @see MathContext#ROUND_HALF_EVEN
* @stable ICU 2.0
*/
public static final int ROUND_HALF_EVEN = com.ibm.icu.math.MathContext.ROUND_HALF_EVEN;
/**
* Rounding mode to round to nearest neighbor, where an equidistant value is rounded up.
*
* @see MathContext#ROUND_HALF_UP
* @stable ICU 2.0
*/
public static final int ROUND_HALF_UP = com.ibm.icu.math.MathContext.ROUND_HALF_UP;
/**
* Rounding mode to assert that no rounding is necessary.
*
* @see MathContext#ROUND_UNNECESSARY
* @stable ICU 2.0
*/
public static final int ROUND_UNNECESSARY = com.ibm.icu.math.MathContext.ROUND_UNNECESSARY;
/**
* Rounding mode to round away from zero.
*
* @see MathContext#ROUND_UP
* @stable ICU 2.0
*/
public static final int ROUND_UP = com.ibm.icu.math.MathContext.ROUND_UP;
/* properties constant private */// locals
private static final byte ispos = 1; // ind: indicates positive (must be 1)
private static final byte iszero = 0; // ind: indicates zero (must be 0)
private static final byte isneg = -1; // ind: indicates negative (must be -1)
// [later could add NaN, +/- infinity, here]
private static final int MinExp = -999999999; // minimum exponent allowed
private static final int MaxExp = 999999999; // maximum exponent allowed
private static final int MinArg = -999999999; // minimum argument integer
private static final int MaxArg = 999999999; // maximum argument integer
private static final com.ibm.icu.math.MathContext plainMC = new com.ibm.icu.math.MathContext(0,
com.ibm.icu.math.MathContext.PLAIN); // context for plain unlimited math
/* properties constant private unused */// present but not referenced
// Serialization version
private static final long serialVersionUID = 8245355804974198832L;
// private static final java.lang.String
// copyright=" Copyright (c) IBM Corporation 1996, 2000. All rights reserved. ";
/* properties static private */
// Precalculated constant arrays (used by byteaddsub)
private static byte bytecar[] = new byte[(90 + 99) + 1]; // carry/borrow array
private static byte bytedig[] = diginit(); // next digit array
/* ----- Instance properties [all private and immutable] ----- */
/* properties private */
/**
* The indicator. This may take the values:
*
* - ispos -- the number is positive
- iszero -- the number is zero
- isneg -- the number is negative
*
*
* @serial
*/
private byte ind; // assumed undefined
// Note: some code below assumes IND = Sign [-1, 0, 1], at present.
// We only need two bits for this, but use a byte [also permits
// smooth future extension].
/**
* The formatting style. This may take the values:
*
* - MathContext.PLAIN -- no exponent needed
- MathContext.SCIENTIFIC -- scientific notation required
-
* MathContext.ENGINEERING -- engineering notation required
*
*
* This property is an optimization; it allows us to defer number layout until it is actually needed as a string,
* hence avoiding unnecessary formatting.
*
* @serial
*/
private byte form = (byte) com.ibm.icu.math.MathContext.PLAIN; // assumed PLAIN
// We only need two bits for this, at present, but use a byte
// [again, to allow for smooth future extension]
/**
* The value of the mantissa.
*
* Once constructed, this may become shared between several BigDecimal objects, so must not be altered.
*
* For efficiency (speed), this is a byte array, with each byte taking a value of 0 -> 9.
*
* If the first byte is 0 then the value of the number is zero (and mant.length=1, except when constructed from a
* plain number, for example, 0.000).
*
* @serial
*/
private byte mant[]; // assumed null
/**
* The exponent.
*
* For fixed point arithmetic, scale is -exp
, and can apply to zero.
*
* Note that this property can have a value less than MinExp when the mantissa has more than one digit.
*
* @serial
*/
private int exp;
// assumed 0
/* ---------------------------------------------------------------- */
/* Constructors */
/* ---------------------------------------------------------------- */
/**
* Constructs a BigDecimal
object from a java.math.BigDecimal
.
*
* Constructs a BigDecimal
as though the parameter had been represented as a String
(using
* its toString
method) and the {@link #BigDecimal(java.lang.String)} constructor had then been used.
* The parameter must not be null
.
*
* (Note: this constructor is provided only in the com.ibm.icu.math
version of the BigDecimal class.
* It would not be present in a java.math
version.)
*
* @param bd The BigDecimal
to be translated.
* @stable ICU 2.0
*/
public BigDecimal(java.math.BigDecimal bd) {
this(bd.toString());
return;
}
/**
* Constructs a BigDecimal
object from a BigInteger
, with scale 0.
*
* Constructs a BigDecimal
which is the exact decimal representation of the BigInteger
,
* with a scale of zero. The value of the BigDecimal
is identical to the value of the BigInteger
*
. The parameter must not be null
.
*
* The BigDecimal
will contain only decimal digits, prefixed with a leading minus sign (hyphen) if the
* BigInteger
is negative. A leading zero will be present only if the BigInteger
is zero.
*
* @param bi The BigInteger
to be converted.
* @stable ICU 2.0
*/
public BigDecimal(java.math.BigInteger bi) {
this(bi.toString(10));
return;
}
// exp remains 0
/**
* Constructs a BigDecimal
object from a BigInteger
and a scale.
*
* Constructs a BigDecimal
which is the exact decimal representation of the BigInteger
,
* scaled by the second parameter, which may not be negative. The value of the BigDecimal
is the
* BigInteger
divided by ten to the power of the scale. The BigInteger
parameter must not be
* null
.
*
* The BigDecimal
will contain only decimal digits, (with an embedded decimal point followed by
* scale
decimal digits if the scale is positive), prefixed with a leading minus sign (hyphen) if the
* BigInteger
is negative. A leading zero will be present only if the BigInteger
is zero.
*
* @param bi The BigInteger
to be converted.
* @param scale The int
specifying the scale.
* @throws NumberFormatException If the scale is negative.
* @stable ICU 2.0
*/
public BigDecimal(java.math.BigInteger bi, int scale) {
this(bi.toString(10));
if (scale < 0)
throw new java.lang.NumberFormatException("Negative scale:" + " " + scale);
exp = -scale; // exponent is -scale
return;
}
/**
* Constructs a BigDecimal
object from an array of characters.
*
* Constructs a BigDecimal
as though a String
had been constructed from the character
* array and the {@link #BigDecimal(java.lang.String)} constructor had then been used. The parameter must not be
* null
.
*
* Using this constructor is faster than using the BigDecimal(String)
constructor if the string is
* already available in character array form.
*
* @param inchars The char[]
array containing the number to be converted.
* @throws NumberFormatException If the parameter is not a valid number.
* @stable ICU 2.0
*/
public BigDecimal(char inchars[]) {
this(inchars, 0, inchars.length);
return;
}
/**
* Constructs a BigDecimal
object from an array of characters.
*
* Constructs a BigDecimal
as though a String
had been constructed from the character
* array (or a subarray of that array) and the {@link #BigDecimal(java.lang.String)} constructor had then been used.
* The first parameter must not be null
, and the subarray must be wholly contained within it.
*
* Using this constructor is faster than using the BigDecimal(String)
constructor if the string is
* already available within a character array.
*
* @param inchars The char[]
array containing the number to be converted.
* @param offset The int
offset into the array of the start of the number to be converted.
* @param length The int
length of the number.
* @throws NumberFormatException If the parameter is not a valid number for any reason.
* @stable ICU 2.0
*/
public BigDecimal(char inchars[], int offset, int length) {
super();
boolean exotic;
boolean hadexp;
int d;
int dotoff;
int last;
int i = 0;
char si = 0;
boolean eneg = false;
int k = 0;
int elen = 0;
int j = 0;
char sj = 0;
int dvalue = 0;
int mag = 0;
// This is the primary constructor; all incoming strings end up
// here; it uses explicit (inline) parsing for speed and to avoid
// generating intermediate (temporary) objects of any kind.
// 1998.06.25: exponent form built only if E/e in string
// 1998.06.25: trailing zeros not removed for zero
// 1999.03.06: no embedded blanks; allow offset and length
if (length <= 0)
bad(inchars); // bad conversion (empty string)
// [bad offset will raise array bounds exception]
/* Handle and step past sign */
ind = ispos; // assume positive
if (inchars[offset] == ('-')) {
length--;
if (length == 0)
bad(inchars); // nothing after sign
ind = isneg;
offset++;
} else if (inchars[offset] == ('+')) {
length--;
if (length == 0)
bad(inchars); // nothing after sign
offset++;
}
/* We're at the start of the number */
exotic = false; // have extra digits
hadexp = false; // had explicit exponent
d = 0; // count of digits found
dotoff = -1; // offset where dot was found
last = -1; // last character of mantissa
{
int $1 = length;
i = offset;
i: for (; $1 > 0; $1--, i++) {
si = inchars[i];
if (si >= '0') // test for Arabic digit
if (si <= '9') {
last = i;
d++; // still in mantissa
continue i;
}
if (si == '.') { // record and ignore
if (dotoff >= 0)
bad(inchars); // two dots
dotoff = i - offset; // offset into mantissa
continue i;
}
if (si != 'e')
if (si != 'E') { // expect an extra digit
if ((!(UCharacter.isDigit(si))))
bad(inchars); // not a number
// defer the base 10 check until later to avoid extra method call
exotic = true; // will need conversion later
last = i;
d++; // still in mantissa
continue i;
}
/* Found 'e' or 'E' -- now process explicit exponent */
// 1998.07.11: sign no longer required
if ((i - offset) > (length - 2))
bad(inchars); // no room for even one digit
eneg = false;
if ((inchars[i + 1]) == ('-')) {
eneg = true;
k = i + 2;
} else if ((inchars[i + 1]) == ('+'))
k = i + 2;
else
k = i + 1;
// k is offset of first expected digit
elen = length - ((k - offset)); // possible number of digits
if ((elen == 0) | (elen > 9))
bad(inchars); // 0 or more than 9 digits
{
int $2 = elen;
j = k;
for (; $2 > 0; $2--, j++) {
sj = inchars[j];
if (sj < '0')
bad(inchars); // always bad
if (sj > '9') { // maybe an exotic digit
if ((!(UCharacter.isDigit(sj))))
bad(inchars); // not a number
dvalue = UCharacter.digit(sj, 10); // check base
if (dvalue < 0)
bad(inchars); // not base 10
} else
dvalue = ((sj)) - (('0'));
exp = (exp * 10) + dvalue;
}
}/* j */
if (eneg)
exp = -exp; // was negative
hadexp = true; // remember we had one
break i; // we are done
}
}/* i */
/* Here when all inspected */
if (d == 0)
bad(inchars); // no mantissa digits
if (dotoff >= 0)
exp = (exp + dotoff) - d; // adjust exponent if had dot
/* strip leading zeros/dot (leave final if all 0's) */
{
int $3 = last - 1;
i = offset;
i: for (; i <= $3; i++) {
si = inchars[i];
if (si == '0') {
offset++;
dotoff--;
d--;
} else if (si == '.') {
offset++; // step past dot
dotoff--;
} else if (si <= '9')
break i;/* non-0 */
else {/* exotic */
if ((UCharacter.digit(si, 10)) != 0)
break i; // non-0 or bad
// is 0 .. strip like '0'
offset++;
dotoff--;
d--;
}
}
}/* i */
/* Create the mantissa array */
mant = new byte[d]; // we know the length
j = offset; // input offset
if (exotic) {
do { // slow: check for exotica
{
int $4 = d;
i = 0;
for (; $4 > 0; $4--, i++) {
if (i == dotoff)
j++; // at dot
sj = inchars[j];
if (sj <= '9')
mant[i] = (byte) (((sj)) - (('0')));/* easy */
else {
dvalue = UCharacter.digit(sj, 10);
if (dvalue < 0)
bad(inchars); // not a number after all
mant[i] = (byte) dvalue;
}
j++;
}
}/* i */
} while (false);
}/* exotica */
else {
do {
{
int $5 = d;
i = 0;
for (; $5 > 0; $5--, i++) {
if (i == dotoff)
j++;
mant[i] = (byte) (((inchars[j])) - (('0')));
j++;
}
}/* i */
} while (false);
}/* simple */
/* Looks good. Set the sign indicator and form, as needed. */
// Trailing zeros are preserved
// The rule here for form is:
// If no E-notation, then request plain notation
// Otherwise act as though add(0,DEFAULT) and request scientific notation
// [form is already PLAIN]
if (mant[0] == 0) {
ind = iszero; // force to show zero
// negative exponent is significant (e.g., -3 for 0.000) if plain
if (exp > 0)
exp = 0; // positive exponent can be ignored
if (hadexp) { // zero becomes single digit from add
mant = ZERO.mant;
exp = 0;
}
} else { // non-zero
// [ind was set earlier]
// now determine form
if (hadexp) {
form = (byte) com.ibm.icu.math.MathContext.SCIENTIFIC;
// 1999.06.29 check for overflow
mag = (exp + mant.length) - 1; // true exponent in scientific notation
if ((mag < MinExp) | (mag > MaxExp))
bad(inchars);
}
}
// say 'BD(c[]): mant[0] mantlen exp ind form:' mant[0] mant.length exp ind form
return;
}
/**
* Constructs a BigDecimal
object directly from a double
.
*
* Constructs a BigDecimal
which is the exact decimal representation of the 64-bit signed binary
* floating point parameter.
*
* Note that this constructor it an exact conversion; it does not give the same result as converting num
*
to a String
using the Double.toString()
method and then using the
* {@link #BigDecimal(java.lang.String)} constructor. To get that result, use the static {@link #valueOf(double)}
* method to construct a BigDecimal
from a double
.
*
* @param num The double
to be converted.
* @throws NumberFormatException If the parameter is infinite or not a number.
* @stable ICU 2.0
*/
public BigDecimal(double num) {
// 1999.03.06: use exactly the old algorithm
// 2000.01.01: note that this constructor does give an exact result,
// so perhaps it should not be deprecated
// 2000.06.18: no longer deprecated
this((new java.math.BigDecimal(num)).toString());
return;
}
/**
* Constructs a BigDecimal
object directly from a int
.
*
* Constructs a BigDecimal
which is the exact decimal representation of the 32-bit signed binary
* integer parameter. The BigDecimal
will contain only decimal digits, prefixed with a leading minus
* sign (hyphen) if the parameter is negative. A leading zero will be present only if the parameter is zero.
*
* @param num The int
to be converted.
* @stable ICU 2.0
*/
public BigDecimal(int num) {
super();
int mun;
int i = 0;
// We fastpath commoners
if (num <= 9)
if (num >= (-9)) {
do {
// very common single digit case
{/* select */
if (num == 0) {
mant = ZERO.mant;
ind = iszero;
} else if (num == 1) {
mant = ONE.mant;
ind = ispos;
} else if (num == (-1)) {
mant = ONE.mant;
ind = isneg;
} else {
{
mant = new byte[1];
if (num > 0) {
mant[0] = (byte) num;
ind = ispos;
} else { // num<-1
mant[0] = (byte) -num;
ind = isneg;
}
}
}
}
return;
} while (false);
}/* singledigit */
/* We work on negative numbers so we handle the most negative number */
if (num > 0) {
ind = ispos;
num = -num;
} else
ind = isneg;/* negative */// [0 case already handled]
// [it is quicker, here, to pre-calculate the length with
// one loop, then allocate exactly the right length of byte array,
// then re-fill it with another loop]
mun = num; // working copy
{
i = 9;
i: for (;; i--) {
mun = mun / 10;
if (mun == 0)
break i;
}
}/* i */
// i is the position of the leftmost digit placed
mant = new byte[10 - i];
{
i = (10 - i) - 1;
i: for (;; i--) {
mant[i] = (byte) -(((byte) (num % 10)));
num = num / 10;
if (num == 0)
break i;
}
}/* i */
return;
}
/**
* Constructs a BigDecimal
object directly from a long
.
*
* Constructs a BigDecimal
which is the exact decimal representation of the 64-bit signed binary
* integer parameter. The BigDecimal
will contain only decimal digits, prefixed with a leading minus
* sign (hyphen) if the parameter is negative. A leading zero will be present only if the parameter is zero.
*
* @param num The long
to be converted.
* @stable ICU 2.0
*/
public BigDecimal(long num) {
super();
long mun;
int i = 0;
// Not really worth fastpathing commoners in this constructor [also,
// we use this to construct the static constants].
// This is much faster than: this(String.valueOf(num).toCharArray())
/* We work on negative num so we handle the most negative number */
if (num > 0) {
ind = ispos;
num = -num;
} else if (num == 0)
ind = iszero;
else
ind = isneg;/* negative */
mun = num;
{
i = 18;
i: for (;; i--) {
mun = mun / 10;
if (mun == 0)
break i;
}
}/* i */
// i is the position of the leftmost digit placed
mant = new byte[19 - i];
{
i = (19 - i) - 1;
i: for (;; i--) {
mant[i] = (byte) -(((byte) (num % 10)));
num = num / 10;
if (num == 0)
break i;
}
}/* i */
return;
}
/**
* Constructs a BigDecimal
object from a String
.
*
* Constructs a BigDecimal
from the parameter, which must not be null
and must represent a
* valid number, as described formally in the documentation referred to {@link BigDecimal above}.
*
* In summary, numbers in String
form must have at least one digit, may have a leading sign, may have a
* decimal point, and exponential notation may be used. They follow conventional syntax, and may not contain blanks.
*
* Some valid strings from which a BigDecimal
might be constructed are:
*
*
*
* "0" -- Zero "12" -- A whole number "-76" -- A signed whole number "12.70" -- Some decimal places "+0.003" -- Plus
* sign is allowed "17." -- The same as 17 ".5" -- The same as 0.5 "4E+9" -- Exponential notation "0.73e-7" --
* Exponential notation
*
*
*
* (Exponential notation means that the number includes an optional sign and a power of ten following an
* 'E
' that indicates how the decimal point will be shifted. Thus the "4E+9"
above is
* just a short way of writing 4000000000
, and the "0.73e-7"
is short for
* 0.000000073
.)
*
* The BigDecimal
constructed from the String is in a standard form, with no blanks, as though the
* {@link #add(BigDecimal)} method had been used to add zero to the number with unlimited precision. If the string
* uses exponential notation (that is, includes an e
or an E
), then the BigDecimal
*
number will be expressed in scientific notation (where the power of ten is adjusted so there is a single
* non-zero digit to the left of the decimal point); in this case if the number is zero then it will be expressed as
* the single digit 0, and if non-zero it will have an exponent unless that exponent would be 0. The exponent must
* fit in nine digits both before and after it is expressed in scientific notation.
*
* Any digits in the parameter must be decimal; that is, Character.digit(c, 10)
(where c
* is the character in question) would not return -1.
*
* @param string The String
to be converted.
* @throws NumberFormatException If the parameter is not a valid number.
* @stable ICU 2.0
*/
public BigDecimal(java.lang.String string) {
this(string.toCharArray(), 0, string.length());
return;
}
/* Make a default BigDecimal object for local use. */
private BigDecimal() {
super();
return;
}
/* ---------------------------------------------------------------- */
/* Operator methods [methods which take a context parameter] */
/* ---------------------------------------------------------------- */
/**
* Returns a plain BigDecimal
whose value is the absolute value of this BigDecimal
.
*
* The same as {@link #abs(MathContext)}, where the context is new MathContext(0, MathContext.PLAIN)
.
*
* The length of the decimal part (the scale) of the result will be this.scale()
*
* @return A BigDecimal
whose value is the absolute value of this BigDecimal
.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal abs() {
return this.abs(plainMC);
}
/**
* Returns a BigDecimal
whose value is the absolute value of this BigDecimal
.
*
* If the current object is zero or positive, then the same result as invoking the {@link #plus(MathContext)} method
* with the same parameter is returned. Otherwise, the same result as invoking the {@link #negate(MathContext)}
* method with the same parameter is returned.
*
* @param set The MathContext
arithmetic settings.
* @return A BigDecimal
whose value is the absolute value of this BigDecimal
.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal abs(com.ibm.icu.math.MathContext set) {
if (this.ind == isneg)
return this.negate(set);
return this.plus(set);
}
/**
* Returns a plain BigDecimal
whose value is this+rhs
, using fixed point arithmetic.
*
* The same as {@link #add(BigDecimal, MathContext)}, where the BigDecimal
is rhs
, and the
* context is new MathContext(0, MathContext.PLAIN)
.
*
* The length of the decimal part (the scale) of the result will be the maximum of the scales of the two operands.
*
* @param rhs The BigDecimal
for the right hand side of the addition.
* @return A BigDecimal
whose value is this+rhs
, using fixed point arithmetic.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal add(com.ibm.icu.math.BigDecimal rhs) {
return this.add(rhs, plainMC);
}
/**
* Returns a BigDecimal
whose value is this+rhs
.
*
* Implements the addition (+
) operator (as defined in the decimal documentation, see
* {@link BigDecimal class header}), and returns the result as a BigDecimal
object.
*
* @param rhs The BigDecimal
for the right hand side of the addition.
* @param set The MathContext
arithmetic settings.
* @return A BigDecimal
whose value is this+rhs
.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal add(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
com.ibm.icu.math.BigDecimal lhs;
int reqdig;
com.ibm.icu.math.BigDecimal res;
byte usel[];
int usellen;
byte user[];
int userlen;
int newlen = 0;
int tlen = 0;
int mult = 0;
byte t[] = null;
int ia = 0;
int ib = 0;
int ea = 0;
int eb = 0;
byte ca = 0;
byte cb = 0;
/* determine requested digits and form */
if (set.lostDigits)
checkdigits(rhs, set.digits);
lhs = this; // name for clarity and proxy
/* Quick exit for add floating 0 */
// plus() will optimize to return same object if possible
if (lhs.ind == 0)
if (set.form != com.ibm.icu.math.MathContext.PLAIN)
return rhs.plus(set);
if (rhs.ind == 0)
if (set.form != com.ibm.icu.math.MathContext.PLAIN)
return lhs.plus(set);
/* Prepare numbers (round, unless unlimited precision) */
reqdig = set.digits; // local copy (heavily used)
if (reqdig > 0) {
if (lhs.mant.length > reqdig)
lhs = clone(lhs).round(set);
if (rhs.mant.length > reqdig)
rhs = clone(rhs).round(set);
// [we could reuse the new LHS for result in this case]
}
res = new com.ibm.icu.math.BigDecimal(); // build result here
/*
* Now see how much we have to pad or truncate lhs or rhs in order to align the numbers. If one number is much
* larger than the other, then the smaller cannot affect the answer [but we may still need to pad with up to
* DIGITS trailing zeros].
*/
// Note sign may be 0 if digits (reqdig) is 0
// usel and user will be the byte arrays passed to the adder; we'll
// use them on all paths except quick exits
usel = lhs.mant;
usellen = lhs.mant.length;
user = rhs.mant;
userlen = rhs.mant.length;
{
do {/* select */
if (lhs.exp == rhs.exp) {/* no padding needed */
// This is the most common, and fastest, path
res.exp = lhs.exp;
} else if (lhs.exp > rhs.exp) { // need to pad lhs and/or truncate rhs
newlen = (usellen + lhs.exp) - rhs.exp;
/*
* If, after pad, lhs would be longer than rhs by digits+1 or more (and digits>0) then rhs cannot
* affect answer, so we only need to pad up to a length of DIGITS+1.
*/
if (newlen >= ((userlen + reqdig) + 1))
if (reqdig > 0) {
// LHS is sufficient
res.mant = usel;
res.exp = lhs.exp;
res.ind = lhs.ind;
if (usellen < reqdig) { // need 0 padding
res.mant = extend(lhs.mant, reqdig);
res.exp = res.exp - ((reqdig - usellen));
}
return res.finish(set, false);
}
// RHS may affect result
res.exp = rhs.exp; // expected final exponent
if (newlen > (reqdig + 1))
if (reqdig > 0) {
// LHS will be max; RHS truncated
tlen = (newlen - reqdig) - 1; // truncation length
userlen = userlen - tlen;
res.exp = res.exp + tlen;
newlen = reqdig + 1;
}
if (newlen > usellen)
usellen = newlen; // need to pad LHS
} else { // need to pad rhs and/or truncate lhs
newlen = (userlen + rhs.exp) - lhs.exp;
if (newlen >= ((usellen + reqdig) + 1))
if (reqdig > 0) {
// RHS is sufficient
res.mant = user;
res.exp = rhs.exp;
res.ind = rhs.ind;
if (userlen < reqdig) { // need 0 padding
res.mant = extend(rhs.mant, reqdig);
res.exp = res.exp - ((reqdig - userlen));
}
return res.finish(set, false);
}
// LHS may affect result
res.exp = lhs.exp; // expected final exponent
if (newlen > (reqdig + 1))
if (reqdig > 0) {
// RHS will be max; LHS truncated
tlen = (newlen - reqdig) - 1; // truncation length
usellen = usellen - tlen;
res.exp = res.exp + tlen;
newlen = reqdig + 1;
}
if (newlen > userlen)
userlen = newlen; // need to pad RHS
}
} while (false);
}/* padder */
/* OK, we have aligned mantissas. Now add or subtract. */
// 1998.06.27 Sign may now be 0 [e.g., 0.000] .. treat as positive
// 1999.05.27 Allow for 00 on lhs [is not larger than 2 on rhs]
// 1999.07.10 Allow for 00 on rhs [is not larger than 2 on rhs]
if (lhs.ind == iszero)
res.ind = ispos;
else
res.ind = lhs.ind; // likely sign, all paths
if (((lhs.ind == isneg) ? 1 : 0) == ((rhs.ind == isneg) ? 1 : 0)) // same sign, 0 non-negative
mult = 1;
else {
do { // different signs, so subtraction is needed
mult = -1; // will cause subtract
/*
* Before we can subtract we must determine which is the larger, as our add/subtract routine only
* handles non-negative results so we may need to swap the operands.
*/
{
do {/* select */
if (rhs.ind == iszero) {
// original A bigger
} else if ((usellen < userlen) | (lhs.ind == iszero)) { // original B bigger
t = usel;
usel = user;
user = t; // swap
tlen = usellen;
usellen = userlen;
userlen = tlen; // ..
res.ind = (byte) -res.ind; // and set sign
} else if (usellen > userlen) {
// original A bigger
} else {
{/* logical lengths the same */// need compare
/* may still need to swap: compare the strings */
ia = 0;
ib = 0;
ea = usel.length - 1;
eb = user.length - 1;
{
compare: for (;;) {
if (ia <= ea)
ca = usel[ia];
else {
if (ib > eb) {/* identical */
if (set.form != com.ibm.icu.math.MathContext.PLAIN)
return ZERO;
// [if PLAIN we must do the subtract, in case of 0.000 results]
break compare;
}
ca = (byte) 0;
}
if (ib <= eb)
cb = user[ib];
else
cb = (byte) 0;
if (ca != cb) {
if (ca < cb) {/* swap needed */
t = usel;
usel = user;
user = t; // swap
tlen = usellen;
usellen = userlen;
userlen = tlen; // ..
res.ind = (byte) -res.ind;
}
break compare;
}
/* mantissas the same, so far */
ia++;
ib++;
}
}/* compare */
} // lengths the same
}
} while (false);
}/* swaptest */
} while (false);
}/* signdiff */
/* here, A is > B if subtracting */
// add [A+B*1] or subtract [A+(B*-1)]
res.mant = byteaddsub(usel, usellen, user, userlen, mult, false);
// [reuse possible only after chop; accounting makes not worthwhile]
// Finish() rounds before stripping leading 0's, then sets form, etc.
return res.finish(set, false);
}
/**
* Compares this BigDecimal
to another, using unlimited precision.
*
* The same as {@link #compareTo(BigDecimal, MathContext)}, where the BigDecimal
is rhs
,
* and the context is new MathContext(0, MathContext.PLAIN)
.
*
* @param rhs The BigDecimal
for the right hand side of the comparison.
* @return An int
whose value is -1, 0, or 1 as this
is numerically less than, equal to,
* or greater than rhs
.
* @stable ICU 2.0
*/
@Override
public int compareTo(com.ibm.icu.math.BigDecimal rhs) {
return this.compareTo(rhs, plainMC);
}
/**
* Compares this BigDecimal
to another.
*
* Implements numeric comparison, (as defined in the decimal documentation, see {@link BigDecimal class header}),
* and returns a result of type int
.
*
* The result will be:
*
*
* -1 if the current object is less than the first parameter
*
*
* 0 if the current object is equal to the first parameter
*
*
* 1 if the current object is greater than the first parameter.
*
*
*
* A {@link #compareTo(BigDecimal)} method is also provided.
*
* @param rhs The BigDecimal
for the right hand side of the comparison.
* @param set The MathContext
arithmetic settings.
* @return An int
whose value is -1, 0, or 1 as this
is numerically less than, equal to,
* or greater than rhs
.
* @stable ICU 2.0
*/
public int compareTo(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
int thislength = 0;
int i = 0;
com.ibm.icu.math.BigDecimal newrhs;
// rhs=null will raise NullPointerException, as per Comparable interface
if (set.lostDigits)
checkdigits(rhs, set.digits);
// [add will recheck in slowpath cases .. but would report -rhs]
if ((this.ind == rhs.ind) & (this.exp == rhs.exp)) {
/* sign & exponent the same [very common] */
thislength = this.mant.length;
if (thislength < rhs.mant.length)
return (byte) -this.ind;
if (thislength > rhs.mant.length)
return this.ind;
/*
* lengths are the same; we can do a straight mantissa compare unless maybe rounding [rounding is very
* unusual]
*/
if ((thislength <= set.digits) | (set.digits == 0)) {
{
int $6 = thislength;
i = 0;
for (; $6 > 0; $6--, i++) {
if (this.mant[i] < rhs.mant[i])
return (byte) -this.ind;
if (this.mant[i] > rhs.mant[i])
return this.ind;
}
}/* i */
return 0; // identical
}
/* drop through for full comparison */
} else {
/* More fastpaths possible */
if (this.ind < rhs.ind)
return -1;
if (this.ind > rhs.ind)
return 1;
}
/* carry out a subtract to make the comparison */
newrhs = clone(rhs); // safe copy
newrhs.ind = (byte) -newrhs.ind; // prepare to subtract
return this.add(newrhs, set).ind; // add, and return sign of result
}
/**
* Returns a plain BigDecimal
whose value is this/rhs
, using fixed point arithmetic.
*
* The same as {@link #divide(BigDecimal, int)}, where the BigDecimal
is rhs
, and the
* rounding mode is {@link MathContext#ROUND_HALF_UP}.
*
* The length of the decimal part (the scale) of the result will be the same as the scale of the current object, if
* the latter were formatted without exponential notation.
*
* @param rhs The BigDecimal
for the right hand side of the division.
* @return A plain BigDecimal
whose value is this/rhs
, using fixed point arithmetic.
* @throws ArithmeticException If rhs
is zero.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal divide(com.ibm.icu.math.BigDecimal rhs) {
return this.dodivide('D', rhs, plainMC, -1);
}
/**
* Returns a plain BigDecimal
whose value is this/rhs
, using fixed point arithmetic and a
* rounding mode.
*
* The same as {@link #divide(BigDecimal, int, int)}, where the BigDecimal
is rhs
, and the
* second parameter is this.scale()
, and the third is round
.
*
* The length of the decimal part (the scale) of the result will therefore be the same as the scale of the current
* object, if the latter were formatted without exponential notation.
*
*
* @param rhs The BigDecimal
for the right hand side of the division.
* @param round The int
rounding mode to be used for the division (see the {@link MathContext} class).
* @return A plain BigDecimal
whose value is this/rhs
, using fixed point arithmetic and
* the specified rounding mode.
* @throws IllegalArgumentException if round
is not a valid rounding mode.
* @throws ArithmeticException if rhs
is zero.
* @throws ArithmeticException if round
is {@link MathContext#ROUND_UNNECESSARY} and this.scale()
is insufficient to represent the result exactly.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal divide(com.ibm.icu.math.BigDecimal rhs, int round) {
com.ibm.icu.math.MathContext set;
set = new com.ibm.icu.math.MathContext(0, com.ibm.icu.math.MathContext.PLAIN, false, round); // [checks round,
// too]
return this.dodivide('D', rhs, set, -1); // take scale from LHS
}
/**
* Returns a plain BigDecimal
whose value is this/rhs
, using fixed point arithmetic and a
* given scale and rounding mode.
*
* The same as {@link #divide(BigDecimal, MathContext)}, where the BigDecimal
is rhs
,
* new MathContext(0, MathContext.PLAIN, false, round)
, except that the length of the decimal part (the
* scale) to be used for the result is explicit rather than being taken from this
.
*
* The length of the decimal part (the scale) of the result will be the same as the scale of the current object, if
* the latter were formatted without exponential notation.
*
*
* @param rhs The BigDecimal
for the right hand side of the division.
* @param scale The int
scale to be used for the result.
* @param round The int
rounding mode to be used for the division (see the {@link MathContext} class).
* @return A plain BigDecimal
whose value is this/rhs
, using fixed point arithmetic and
* the specified rounding mode.
* @throws IllegalArgumentException if round
is not a valid rounding mode.
* @throws ArithmeticException if rhs
is zero.
* @throws ArithmeticException if scale
is negative.
* @throws ArithmeticException if round
is {@link MathContext#ROUND_UNNECESSARY} and scale
is insufficient
* to represent the result exactly.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal divide(com.ibm.icu.math.BigDecimal rhs, int scale, int round) {
com.ibm.icu.math.MathContext set;
if (scale < 0)
throw new java.lang.ArithmeticException("Negative scale:" + " " + scale);
set = new com.ibm.icu.math.MathContext(0, com.ibm.icu.math.MathContext.PLAIN, false, round); // [checks round]
return this.dodivide('D', rhs, set, scale);
}
/**
* Returns a BigDecimal
whose value is this/rhs
.
*
* Implements the division (/
) operator (as defined in the decimal documentation, see
* {@link BigDecimal class header}), and returns the result as a BigDecimal
object.
*
* @param rhs The BigDecimal
for the right hand side of the division.
* @param set The MathContext
arithmetic settings.
* @return A BigDecimal
whose value is this/rhs
.
* @throws ArithmeticException if rhs
is zero.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal divide(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
return this.dodivide('D', rhs, set, -1);
}
/**
* Returns a plain BigDecimal
whose value is the integer part of this/rhs
.
*
* The same as {@link #divideInteger(BigDecimal, MathContext)}, where the BigDecimal
is rhs
*
, and the context is new MathContext(0, MathContext.PLAIN)
.
*
* @param rhs The BigDecimal
for the right hand side of the integer division.
* @return A BigDecimal
whose value is the integer part of this/rhs
.
* @throws ArithmeticException if rhs
is zero.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal divideInteger(com.ibm.icu.math.BigDecimal rhs) {
// scale 0 to drop .000 when plain
return this.dodivide('I', rhs, plainMC, 0);
}
/**
* Returns a BigDecimal
whose value is the integer part of this/rhs
.
*
* Implements the integer division operator (as defined in the decimal documentation, see {@link BigDecimal class
* header}), and returns the result as a BigDecimal
object.
*
* @param rhs The BigDecimal
for the right hand side of the integer division.
* @param set The MathContext
arithmetic settings.
* @return A BigDecimal
whose value is the integer part of this/rhs
.
* @throws ArithmeticException if rhs
is zero.
* @throws ArithmeticException if the result will not fit in the number of digits specified for the context.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal divideInteger(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
// scale 0 to drop .000 when plain
return this.dodivide('I', rhs, set, 0);
}
/**
* Returns a plain BigDecimal
whose value is the maximum of this
and rhs
.
*
* The same as {@link #max(BigDecimal, MathContext)}, where the BigDecimal
is rhs
, and the
* context is new MathContext(0, MathContext.PLAIN)
.
*
* @param rhs The BigDecimal
for the right hand side of the comparison.
* @return A BigDecimal
whose value is the maximum of this
and rhs
.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal max(com.ibm.icu.math.BigDecimal rhs) {
return this.max(rhs, plainMC);
}
/**
* Returns a BigDecimal
whose value is the maximum of this
and rhs
.
*
* Returns the larger of the current object and the first parameter.
*
* If calling the {@link #compareTo(BigDecimal, MathContext)} method with the same parameters would return 1
*
or 0
, then the result of calling the {@link #plus(MathContext)} method on the current object
* (using the same MathContext
parameter) is returned. Otherwise, the result of calling the
* {@link #plus(MathContext)} method on the first parameter object (using the same MathContext
* parameter) is returned.
*
* @param rhs The BigDecimal
for the right hand side of the comparison.
* @param set The MathContext
arithmetic settings.
* @return A BigDecimal
whose value is the maximum of this
and rhs
.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal max(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
if ((this.compareTo(rhs, set)) >= 0)
return this.plus(set);
else
return rhs.plus(set);
}
/**
* Returns a plain BigDecimal
whose value is the minimum of this
and rhs
.
*
* The same as {@link #min(BigDecimal, MathContext)}, where the BigDecimal
is rhs
, and the
* context is new MathContext(0, MathContext.PLAIN)
.
*
* @param rhs The BigDecimal
for the right hand side of the comparison.
* @return A BigDecimal
whose value is the minimum of this
and rhs
.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal min(com.ibm.icu.math.BigDecimal rhs) {
return this.min(rhs, plainMC);
}
/**
* Returns a BigDecimal
whose value is the minimum of this
and rhs
.
*
* Returns the smaller of the current object and the first parameter.
*
* If calling the {@link #compareTo(BigDecimal, MathContext)} method with the same parameters would return -1
*
or 0
, then the result of calling the {@link #plus(MathContext)} method on the current object
* (using the same MathContext
parameter) is returned. Otherwise, the result of calling the
* {@link #plus(MathContext)} method on the first parameter object (using the same MathContext
* parameter) is returned.
*
* @param rhs The BigDecimal
for the right hand side of the comparison.
* @param set The MathContext
arithmetic settings.
* @return A BigDecimal
whose value is the minimum of this
and rhs
.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal min(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
if ((this.compareTo(rhs, set)) <= 0)
return this.plus(set);
else
return rhs.plus(set);
}
/**
* Returns a plain BigDecimal
whose value is this*rhs
, using fixed point arithmetic.
*
* The same as {@link #add(BigDecimal, MathContext)}, where the BigDecimal
is rhs
, and the
* context is new MathContext(0, MathContext.PLAIN)
.
*
* The length of the decimal part (the scale) of the result will be the sum of the scales of the operands, if they
* were formatted without exponential notation.
*
* @param rhs The BigDecimal
for the right hand side of the multiplication.
* @return A BigDecimal
whose value is this*rhs
, using fixed point arithmetic.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal multiply(com.ibm.icu.math.BigDecimal rhs) {
return this.multiply(rhs, plainMC);
}
/**
* Returns a BigDecimal
whose value is this*rhs
.
*
* Implements the multiplication (*
) operator (as defined in the decimal documentation, see
* {@link BigDecimal class header}), and returns the result as a BigDecimal
object.
*
* @param rhs The BigDecimal
for the right hand side of the multiplication.
* @param set The MathContext
arithmetic settings.
* @return A BigDecimal
whose value is this*rhs
.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal multiply(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
com.ibm.icu.math.BigDecimal lhs;
int padding;
int reqdig;
byte multer[] = null;
byte multand[] = null;
int multandlen;
int acclen = 0;
com.ibm.icu.math.BigDecimal res;
byte acc[];
int n = 0;
byte mult = 0;
if (set.lostDigits)
checkdigits(rhs, set.digits);
lhs = this; // name for clarity and proxy
/* Prepare numbers (truncate, unless unlimited precision) */
padding = 0; // trailing 0's to add
reqdig = set.digits; // local copy
if (reqdig > 0) {
if (lhs.mant.length > reqdig)
lhs = clone(lhs).round(set);
if (rhs.mant.length > reqdig)
rhs = clone(rhs).round(set);
// [we could reuse the new LHS for result in this case]
} else {/* unlimited */
// fixed point arithmetic will want every trailing 0; we add these
// after the calculation rather than before, for speed.
if (lhs.exp > 0)
padding = padding + lhs.exp;
if (rhs.exp > 0)
padding = padding + rhs.exp;
}
// For best speed, as in DMSRCN, we use the shorter number as the
// multiplier and the longer as the multiplicand.
// 1999.12.22: We used to special case when the result would fit in
// a long, but with Java 1.3 this gave no advantage.
if (lhs.mant.length < rhs.mant.length) {
multer = lhs.mant;
multand = rhs.mant;
} else {
multer = rhs.mant;
multand = lhs.mant;
}
/* Calculate how long result byte array will be */
multandlen = (multer.length + multand.length) - 1; // effective length
// optimize for 75% of the cases where a carry is expected...
if ((multer[0] * multand[0]) > 9)
acclen = multandlen + 1;
else
acclen = multandlen;
/* Now the main long multiplication loop */
res = new com.ibm.icu.math.BigDecimal(); // where we'll build result
acc = new byte[acclen]; // accumulator, all zeros
// 1998.07.01: calculate from left to right so that accumulator goes
// to likely final length on first addition; this avoids a one-digit
// extension (and object allocation) each time around the loop.
// Initial number therefore has virtual zeros added to right.
{
int $7 = multer.length;
n = 0;
for (; $7 > 0; $7--, n++) {
mult = multer[n];
if (mult != 0) { // [optimization]
// accumulate [accumulator is reusable array]
acc = byteaddsub(acc, acc.length, multand, multandlen, mult, true);
}
// divide multiplicand by 10 for next digit to right
multandlen--; // 'virtual length'
}
}/* n */
res.ind = (byte) (lhs.ind * rhs.ind); // final sign
res.exp = (lhs.exp + rhs.exp) - padding; // final exponent
// [overflow is checked by finish]
/* add trailing zeros to the result, if necessary */
if (padding == 0)
res.mant = acc;
else
res.mant = extend(acc, acc.length + padding); // add trailing 0s
return res.finish(set, false);
}
/**
* Returns a plain BigDecimal
whose value is -this
.
*
* The same as {@link #negate(MathContext)}, where the context is new MathContext(0, MathContext.PLAIN)
* .
*
* The length of the decimal part (the scale) of the result will be be this.scale()
*
*
* @return A BigDecimal
whose value is -this
.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal negate() {
return this.negate(plainMC);
}
/**
* Returns a BigDecimal
whose value is -this
.
*
* Implements the negation (Prefix -
) operator (as defined in the decimal documentation, see
* {@link BigDecimal class header}), and returns the result as a BigDecimal
object.
*
* @param set The MathContext
arithmetic settings.
* @return A BigDecimal
whose value is -this
.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal negate(com.ibm.icu.math.MathContext set) {
com.ibm.icu.math.BigDecimal res;
// Originally called minus(), changed to matched Java precedents
// This simply clones, flips the sign, and possibly rounds
if (set.lostDigits)
checkdigits((com.ibm.icu.math.BigDecimal) null, set.digits);
res = clone(this); // safe copy
res.ind = (byte) -res.ind;
return res.finish(set, false);
}
/**
* Returns a plain BigDecimal
whose value is +this
. Note that this
is not
* necessarily a plain BigDecimal
, but the result will always be.
*
* The same as {@link #plus(MathContext)}, where the context is new MathContext(0, MathContext.PLAIN)
.
*
* The length of the decimal part (the scale) of the result will be be this.scale()
*
* @return A BigDecimal
whose value is +this
.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal plus() {
return this.plus(plainMC);
}
/**
* Returns a BigDecimal
whose value is +this
.
*
* Implements the plus (Prefix +
) operator (as defined in the decimal documentation, see
* {@link BigDecimal class header}), and returns the result as a BigDecimal
object.
*
* This method is useful for rounding or otherwise applying a context to a decimal value.
*
* @param set The MathContext
arithmetic settings.
* @return A BigDecimal
whose value is +this
.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal plus(com.ibm.icu.math.MathContext set) {
// This clones and forces the result to the new settings
// May return same object
if (set.lostDigits)
checkdigits((com.ibm.icu.math.BigDecimal) null, set.digits);
// Optimization: returns same object for some common cases
if (set.form == com.ibm.icu.math.MathContext.PLAIN)
if (this.form == com.ibm.icu.math.MathContext.PLAIN) {
if (this.mant.length <= set.digits)
return this;
if (set.digits == 0)
return this;
}
return clone(this).finish(set, false);
}
/**
* Returns a plain BigDecimal
whose value is this**rhs
, using fixed point arithmetic.
*
* The same as {@link #pow(BigDecimal, MathContext)}, where the BigDecimal
is rhs
, and the
* context is new MathContext(0, MathContext.PLAIN)
.
*
* The parameter is the power to which the this
will be raised; it must be in the range 0 through
* 999999999, and must have a decimal part of zero. Note that these restrictions may be removed in the future, so
* they should not be used as a test for a whole number.
*
* In addition, the power must not be negative, as no MathContext
is used and so the result would then
* always be 0.
*
* @param rhs The BigDecimal
for the right hand side of the operation (the power).
* @return A BigDecimal
whose value is this**rhs
, using fixed point arithmetic.
* @throws ArithmeticException if rhs
is out of range or is not a whole number.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal pow(com.ibm.icu.math.BigDecimal rhs) {
return this.pow(rhs, plainMC);
}
// The name for this method is inherited from the precedent set by the
// BigInteger and Math classes.
/**
* Returns a BigDecimal
whose value is this**rhs
.
*
* Implements the power (^
) operator (as defined in the decimal documentation, see
* {@link BigDecimal class header}), and returns the result as a BigDecimal
object.
*
* The first parameter is the power to which the this
will be raised; it must be in the range
* -999999999 through 999999999, and must have a decimal part of zero. Note that these restrictions may be removed
* in the future, so they should not be used as a test for a whole number.
*
* If the digits
setting of the MathContext
parameter is 0, the power must be zero or
* positive.
*
* @param rhs The BigDecimal
for the right hand side of the operation (the power).
* @param set The MathContext
arithmetic settings.
* @return A BigDecimal
whose value is this**rhs
.
* @throws ArithmeticException if rhs
is out of range or is not a whole number.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal pow(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
int n;
com.ibm.icu.math.BigDecimal lhs;
int reqdig;
int workdigits = 0;
int L = 0;
com.ibm.icu.math.MathContext workset;
com.ibm.icu.math.BigDecimal res;
boolean seenbit;
int i = 0;
if (set.lostDigits)
checkdigits(rhs, set.digits);
n = rhs.intcheck(MinArg, MaxArg); // check RHS by the rules
lhs = this; // clarified name
reqdig = set.digits; // local copy (heavily used)
if (reqdig == 0) {
if (rhs.ind == isneg)
throw new java.lang.ArithmeticException("Negative power:" + " " + rhs.toString());
workdigits = 0;
} else {/* non-0 digits */
if ((rhs.mant.length + rhs.exp) > reqdig)
throw new java.lang.ArithmeticException("Too many digits:" + " " + rhs.toString());
/* Round the lhs to DIGITS if need be */
if (lhs.mant.length > reqdig)
lhs = clone(lhs).round(set);
/* L for precision calculation [see ANSI X3.274-1996] */
L = rhs.mant.length + rhs.exp; // length without decimal zeros/exp
workdigits = (reqdig + L) + 1; // calculate the working DIGITS
}
/* Create a copy of set for working settings */
// Note: no need to check for lostDigits again.
// 1999.07.17 Note: this construction must follow RHS check
workset = new com.ibm.icu.math.MathContext(workdigits, set.form, false, set.roundingMode);
res = ONE; // accumulator
if (n == 0)
return res; // x**0 == 1
if (n < 0)
n = -n; // [rhs.ind records the sign]
seenbit = false; // set once we've seen a 1-bit
{
i = 1;
i: for (;; i++) { // for each bit [top bit ignored]
n = n + n; // shift left 1 bit
if (n < 0) { // top bit is set
seenbit = true; // OK, we're off
res = res.multiply(lhs, workset); // acc=acc*x
}
if (i == 31)
break i; // that was the last bit
if ((!seenbit))
continue i; // we don't have to square 1
res = res.multiply(res, workset); // acc=acc*acc [square]
}
}/* i */// 32 bits
if (rhs.ind < 0) // was a **-n [hence digits>0]
res = ONE.divide(res, workset); // .. so acc=1/acc
return res.finish(set, true); // round and strip [original digits]
}
/**
* Returns a plain BigDecimal
whose value is the remainder of this/rhs
, using fixed point
* arithmetic.
*
* The same as {@link #remainder(BigDecimal, MathContext)}, where the BigDecimal
is rhs
,
* and the context is new MathContext(0, MathContext.PLAIN)
.
*
* This is not the modulo operator -- the result may be negative.
*
* @param rhs The BigDecimal
for the right hand side of the remainder operation.
* @return A BigDecimal
whose value is the remainder of this/rhs
, using fixed point
* arithmetic.
* @throws ArithmeticException if rhs
is zero.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal remainder(com.ibm.icu.math.BigDecimal rhs) {
return this.dodivide('R', rhs, plainMC, -1);
}
/**
* Returns a BigDecimal
whose value is the remainder of this/rhs
.
*
* Implements the remainder operator (as defined in the decimal documentation, see {@link BigDecimal class header}),
* and returns the result as a BigDecimal
object.
*
* This is not the modulo operator -- the result may be negative.
*
* @param rhs The BigDecimal
for the right hand side of the remainder operation.
* @param set The MathContext
arithmetic settings.
* @return A BigDecimal
whose value is the remainder of this+rhs
.
* @throws ArithmeticException if rhs
is zero.
* @throws ArithmeticException if the integer part of the result will not fit in the number of digits specified for the context.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal remainder(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
return this.dodivide('R', rhs, set, -1);
}
/**
* Returns a plain BigDecimal
whose value is this-rhs
, using fixed point arithmetic.
*
* The same as {@link #subtract(BigDecimal, MathContext)}, where the BigDecimal
is rhs
,
* and the context is new MathContext(0, MathContext.PLAIN)
.
*
* The length of the decimal part (the scale) of the result will be the maximum of the scales of the two operands.
*
* @param rhs The BigDecimal
for the right hand side of the subtraction.
* @return A BigDecimal
whose value is this-rhs
, using fixed point arithmetic.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal subtract(com.ibm.icu.math.BigDecimal rhs) {
return this.subtract(rhs, plainMC);
}
/**
* Returns a BigDecimal
whose value is this-rhs
.
*
* Implements the subtraction (-
) operator (as defined in the decimal documentation, see
* {@link BigDecimal class header}), and returns the result as a BigDecimal
object.
*
* @param rhs The BigDecimal
for the right hand side of the subtraction.
* @param set The MathContext
arithmetic settings.
* @return A BigDecimal
whose value is this-rhs
.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal subtract(com.ibm.icu.math.BigDecimal rhs, com.ibm.icu.math.MathContext set) {
com.ibm.icu.math.BigDecimal newrhs;
if (set.lostDigits)
checkdigits(rhs, set.digits);
// [add will recheck .. but would report -rhs]
/* carry out the subtraction */
// we could fastpath -0, but it is too rare.
newrhs = clone(rhs); // safe copy
newrhs.ind = (byte) -newrhs.ind; // prepare to subtract
return this.add(newrhs, set); // arithmetic
}
/* ---------------------------------------------------------------- */
/* Other methods */
/* ---------------------------------------------------------------- */
/**
* Converts this BigDecimal
to a byte
. If the BigDecimal
has a non-zero
* decimal part or is out of the possible range for a byte
(8-bit signed integer) result then an
* ArithmeticException
is thrown.
*
* @return A byte
equal in value to this
.
* @throws ArithmeticException if this
has a non-zero decimal part, or will not fit in a byte
.
* @stable ICU 2.0
*/
public byte byteValueExact() {
int num;
num = this.intValueExact(); // will check decimal part too
if ((num > 127) | (num < (-128)))
throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
return (byte) num;
}
/**
* Converts this BigDecimal
to a double
. If the BigDecimal
is out of the
* possible range for a double
(64-bit signed floating point) result then an ArithmeticException
*
is thrown.
*
* The double produced is identical to result of expressing the BigDecimal
as a String
and
* then converting it using the Double(String)
constructor; this can result in values of
* Double.NEGATIVE_INFINITY
or Double.POSITIVE_INFINITY
.
*
* @return A double
corresponding to this
.
* @stable ICU 2.0
*/
@Override
public double doubleValue() {
// We go via a String [as does BigDecimal in JDK 1.2]
// Next line could possibly raise NumberFormatException
return java.lang.Double.valueOf(this.toString()).doubleValue();
}
/**
* Compares this BigDecimal
with rhs
for equality.
*
* If the parameter is null
, or is not an instance of the BigDecimal type, or is not exactly equal to
* the current BigDecimal
object, then false is returned. Otherwise, true is returned.
*
* "Exactly equal", here, means that the String
representations of the BigDecimal
numbers
* are identical (they have the same characters in the same sequence).
*
* The {@link #compareTo(BigDecimal, MathContext)} method should be used for more general comparisons.
*
* @param obj The Object
for the right hand side of the comparison.
* @return A boolean
whose value true if and only if the operands have identical string
* representations.
* @throws ClassCastException if rhs
cannot be cast to a BigDecimal
object.
* @stable ICU 2.0
* @see #compareTo(BigDecimal)
* @see #compareTo(BigDecimal, MathContext)
*/
@Override
public boolean equals(java.lang.Object obj) {
com.ibm.icu.math.BigDecimal rhs;
int i = 0;
char lca[] = null;
char rca[] = null;
// We are equal iff toString of both are exactly the same
if (obj == null)
return false; // not equal
if ((!(((obj instanceof com.ibm.icu.math.BigDecimal)))))
return false; // not a decimal
rhs = (com.ibm.icu.math.BigDecimal) obj; // cast; we know it will work
if (this.ind != rhs.ind)
return false; // different signs never match
if (((this.mant.length == rhs.mant.length) & (this.exp == rhs.exp)) & (this.form == rhs.form))
{ // mantissas say all
// here with equal-length byte arrays to compare
{
int $8 = this.mant.length;
i = 0;
for (; $8 > 0; $8--, i++) {
if (this.mant[i] != rhs.mant[i])
return false;
}
}/* i */
} else { // need proper layout
lca = this.layout(); // layout to character array
rca = rhs.layout();
if (lca.length != rca.length)
return false; // mismatch
// here with equal-length character arrays to compare
{
int $9 = lca.length;
i = 0;
for (; $9 > 0; $9--, i++) {
if (lca[i] != rca[i])
return false;
}
}/* i */
}
return true; // arrays have identical content
}
/**
* Converts this BigDecimal
to a float
. If the BigDecimal
is out of the
* possible range for a float
(32-bit signed floating point) result then an ArithmeticException
*
is thrown.
*
* The float produced is identical to result of expressing the BigDecimal
as a String
and
* then converting it using the Float(String)
constructor; this can result in values of
* Float.NEGATIVE_INFINITY
or Float.POSITIVE_INFINITY
.
*
* @return A float
corresponding to this
.
* @stable ICU 2.0
*/
@Override
public float floatValue() {
return java.lang.Float.valueOf(this.toString()).floatValue();
}
/**
* Returns the String
representation of this BigDecimal
, modified by layout parameters.
*
* This method is provided as a primitive for use by more sophisticated classes, such as DecimalFormat
*
, that can apply locale-sensitive editing of the result. The level of formatting that it provides is a
* necessary part of the BigDecimal class as it is sensitive to and must follow the calculation and rounding rules
* for BigDecimal arithmetic. However, if the function is provided elsewhere, it may be removed from this class.
*
*
* The parameters, for both forms of the format
method are all of type int
. A value of -1
* for any parameter indicates that the default action or value for that parameter should be used.
*
* The parameters, before
and after
, specify the number of characters to be used for the
* integer part and decimal part of the result respectively. Exponential notation is not used. If either parameter
* is -1 (which indicates the default action), the number of characters used will be exactly as many as are needed
* for that part.
*
* before
must be a positive number; if it is larger than is needed to contain the integer part, that
* part is padded on the left with blanks to the requested length. If before
is not large enough to
* contain the integer part of the number (including the sign, for negative numbers) an exception is thrown.
*
* after
must be a non-negative number; if it is not the same size as the decimal part of the number,
* the number will be rounded (or extended with zeros) to fit. Specifying 0 for after
will cause the
* number to be rounded to an integer (that is, it will have no decimal part or decimal point). The rounding method
* will be the default, MathContext.ROUND_HALF_UP
.
*
* Other rounding methods, and the use of exponential notation, can be selected by using
* {@link #format(int,int,int,int,int,int)}. Using the two-parameter form of the method has exactly the same effect
* as using the six-parameter form with the final four parameters all being -1.
*
* @param before The int
specifying the number of places before the decimal point. Use -1 for 'as many as are needed'.
* @param after The int
specifying the number of places after the decimal point. Use -1 for 'as many as are needed'.
* @return A String
representing this BigDecimal
, laid out according to the specified parameters
* @throws ArithmeticException if the number cannot be laid out as requested.
* @throws IllegalArgumentException if a parameter is out of range.
* @stable ICU 2.0
* @see #toString
* @see #toCharArray
*/
public java.lang.String format(int before, int after) {
return format(before, after, -1, -1, com.ibm.icu.math.MathContext.SCIENTIFIC, ROUND_HALF_UP);
}
/**
* Returns the String
representation of this BigDecimal
, modified by layout parameters and
* allowing exponential notation.
*
* This method is provided as a primitive for use by more sophisticated classes, such as DecimalFormat
*
, that can apply locale-sensitive editing of the result. The level of formatting that it provides is a
* necessary part of the BigDecimal class as it is sensitive to and must follow the calculation and rounding rules
* for BigDecimal arithmetic. However, if the function is provided elsewhere, it may be removed from this class.
*
*
* The parameters are all of type int
. A value of -1 for any parameter indicates that the default
* action or value for that parameter should be used.
*
* The first two parameters (before
and after
) specify the number of characters to be used
* for the integer part and decimal part of the result respectively, as defined for {@link #format(int,int)}. If
* either of these is -1 (which indicates the default action), the number of characters used will be exactly as many
* as are needed for that part.
*
* The remaining parameters control the use of exponential notation and rounding. Three (explaces
,
* exdigits
, and exform
) control the exponent part of the result. As before, the default
* action for any of these parameters may be selected by using the value -1.
*
* explaces
must be a positive number; it sets the number of places (digits after the sign of the
* exponent) to be used for any exponent part, the default (when explaces
is -1) being to use as many
* as are needed. If explaces
is not -1, space is always reserved for an exponent; if one is not needed
* (for example, if the exponent will be 0) then explaces
+2 blanks are appended to the result.
* (This preserves vertical alignment of similarly formatted numbers in a monospace font.) If explaces
*
is not -1 and is not large enough to contain the exponent, an exception is thrown.
*
* exdigits
sets the trigger point for use of exponential notation. If, before any rounding, the number
* of places needed before the decimal point exceeds exdigits
, or if the absolute value of the result
* is less than 0.000001
, then exponential form will be used, provided that exdigits
was
* specified. When exdigits
is -1, exponential notation will never be used. If 0 is specified for
* exdigits
, exponential notation is always used unless the exponent would be 0.
*
* exform
sets the form for exponential notation (if needed). It may be either
* {@link MathContext#SCIENTIFIC} or {@link MathContext#ENGINEERING}. If the latter, engineering, form is requested,
* up to three digits (plus sign, if negative) may be needed for the integer part of the result (before
* ). Otherwise, only one digit (plus sign, if negative) is needed.
*
* Finally, the sixth argument, exround
, selects the rounding algorithm to be used, and must be one of
* the values indicated by a public constant in the {@link MathContext} class whose name starts with ROUND_
*
. The default (ROUND_HALF_UP
) may also be selected by using the value -1, as before.
*
* The special value MathContext.ROUND_UNNECESSARY
may be used to detect whether non-zero digits are
* discarded -- if exround
has this value than if non-zero digits would be discarded (rounded) during
* formatting then an ArithmeticException
is thrown.
*
* @param before The int
specifying the number of places before the decimal point. Use -1 for 'as many as
* are needed'.
* @param after The int
specifying the number of places after the decimal point. Use -1 for 'as many as
* are needed'.
* @param explaces The int
specifying the number of places to be used for any exponent. Use -1 for 'as many
* as are needed'.
* @param exdigits The int
specifying the trigger (digits before the decimal point) which if exceeded causes
* exponential notation to be used. Use 0 to force exponential notation. Use -1 to force plain notation
* (no exponential notation).
* @param exformint The int
specifying the form of exponential notation to be used (
* {@link MathContext#SCIENTIFIC} or {@link MathContext#ENGINEERING}).
* @param exround The int
specifying the rounding mode to use. Use -1 for the default,
* {@link MathContext#ROUND_HALF_UP}.
* @return A String
representing this BigDecimal
, laid out according to the specified
* parameters
* @throws ArithmeticException if the number cannot be laid out as requested.
* @throws IllegalArgumentException if a parameter is out of range.
* @see #toString
* @see #toCharArray
* @stable ICU 2.0
*/
public java.lang.String format(int before, int after, int explaces, int exdigits, int exformint, int exround) {
com.ibm.icu.math.BigDecimal num;
int mag = 0;
int thisafter = 0;
int lead = 0;
byte newmant[] = null;
int chop = 0;
int need = 0;
int oldexp = 0;
char a[];
int p = 0;
char newa[] = null;
int i = 0;
int places = 0;
/* Check arguments */
if ((before < (-1)) | (before == 0))
badarg("format", 1, java.lang.String.valueOf(before));
if (after < (-1))
badarg("format", 2, java.lang.String.valueOf(after));
if ((explaces < (-1)) | (explaces == 0))
badarg("format", 3, java.lang.String.valueOf(explaces));
if (exdigits < (-1))
badarg("format", 4, java.lang.String.valueOf(explaces));
{/* select */
if (exformint == com.ibm.icu.math.MathContext.SCIENTIFIC) {
} else if (exformint == com.ibm.icu.math.MathContext.ENGINEERING) {
} else if (exformint == (-1))
exformint = com.ibm.icu.math.MathContext.SCIENTIFIC;
// note PLAIN isn't allowed
else {
badarg("format", 5, java.lang.String.valueOf(exformint));
}
}
// checking the rounding mode is done by trying to construct a
// MathContext object with that mode; it will fail if bad
if (exround != ROUND_HALF_UP) {
try { // if non-default...
if (exround == (-1))
exround = ROUND_HALF_UP;
else
new com.ibm.icu.math.MathContext(9, com.ibm.icu.math.MathContext.SCIENTIFIC, false, exround);
} catch (java.lang.IllegalArgumentException $10) {
badarg("format", 6, java.lang.String.valueOf(exround));
}
}
num = clone(this); // make private copy
/*
* Here: num is BigDecimal to format before is places before point [>0] after is places after point [>=0]
* explaces is exponent places [>0] exdigits is exponent digits [>=0] exformint is exponent form [one of two]
* exround is rounding mode [one of eight] 'before' through 'exdigits' are -1 if not specified
*/
/* determine form */
{
do {/* select */
if (exdigits == (-1))
num.form = (byte) com.ibm.icu.math.MathContext.PLAIN;
else if (num.ind == iszero)
num.form = (byte) com.ibm.icu.math.MathContext.PLAIN;
else {
// determine whether triggers
mag = num.exp + num.mant.length;
if (mag > exdigits)
num.form = (byte) exformint;
else if (mag < (-5))
num.form = (byte) exformint;
else
num.form = (byte) com.ibm.icu.math.MathContext.PLAIN;
}
} while (false);
}/* setform */
/*
* If 'after' was specified then we may need to adjust the mantissa. This is a little tricky, as we must conform
* to the rules of exponential layout if necessary (e.g., we cannot end up with 10.0 if scientific).
*/
if (after >= 0) {
setafter: for (;;) {
// calculate the current after-length
{/* select */
if (num.form == com.ibm.icu.math.MathContext.PLAIN)
thisafter = -num.exp; // has decimal part
else if (num.form == com.ibm.icu.math.MathContext.SCIENTIFIC)
thisafter = num.mant.length - 1;
else { // engineering
lead = (((num.exp + num.mant.length) - 1)) % 3; // exponent to use
if (lead < 0)
lead = 3 + lead; // negative exponent case
lead++; // number of leading digits
if (lead >= num.mant.length)
thisafter = 0;
else
thisafter = num.mant.length - lead;
}
}
if (thisafter == after)
break setafter; // we're in luck
if (thisafter < after) { // need added trailing zeros
// [thisafter can be negative]
newmant = extend(num.mant, (num.mant.length + after) - thisafter);
num.mant = newmant;
num.exp = num.exp - ((after - thisafter)); // adjust exponent
if (num.exp < MinExp)
throw new java.lang.ArithmeticException("Exponent Overflow:" + " " + num.exp);
break setafter;
}
// We have too many digits after the decimal point; this could
// cause a carry, which could change the mantissa...
// Watch out for implied leading zeros in PLAIN case
chop = thisafter - after; // digits to lop [is >0]
if (chop > num.mant.length) { // all digits go, no chance of carry
// carry on with zero
num.mant = ZERO.mant;
num.ind = iszero;
num.exp = 0;
continue setafter; // recheck: we may need trailing zeros
}
// we have a digit to inspect from existing mantissa
// round the number as required
need = num.mant.length - chop; // digits to end up with [may be 0]
oldexp = num.exp; // save old exponent
num.round(need, exround);
// if the exponent grew by more than the digits we chopped, then
// we must have had a carry, so will need to recheck the layout
if ((num.exp - oldexp) == chop)
break setafter; // number did not have carry
// mantissa got extended .. so go around and check again
}
}/* setafter */
a = num.layout(); // lay out, with exponent if required, etc.
/* Here we have laid-out number in 'a' */
// now apply 'before' and 'explaces' as needed
if (before > 0) {
// look for '.' or 'E'
{
int $11 = a.length;
p = 0;
p: for (; $11 > 0; $11--, p++) {
if (a[p] == '.')
break p;
if (a[p] == 'E')
break p;
}
}/* p */
// p is now offset of '.', 'E', or character after end of array
// that is, the current length of before part
if (p > before)
badarg("format", 1, java.lang.String.valueOf(before)); // won't fit
if (p < before) { // need leading blanks
newa = new char[(a.length + before) - p];
{
int $12 = before - p;
i = 0;
for (; $12 > 0; $12--, i++) {
newa[i] = ' ';
}
}/* i */
java.lang.System.arraycopy(a, 0, newa, i, a.length);
a = newa;
}
// [if p=before then it's just the right length]
}
if (explaces > 0) {
// look for 'E' [cannot be at offset 0]
{
int $13 = a.length - 1;
p = a.length - 1;
p: for (; $13 > 0; $13--, p--) {
if (a[p] == 'E')
break p;
}
}/* p */
// p is now offset of 'E', or 0
if (p == 0) { // no E part; add trailing blanks
newa = new char[(a.length + explaces) + 2];
java.lang.System.arraycopy(a, 0, newa, 0, a.length);
{
int $14 = explaces + 2;
i = a.length;
for (; $14 > 0; $14--, i++) {
newa[i] = ' ';
}
}/* i */
a = newa;
} else {/* found E */// may need to insert zeros
places = (a.length - p) - 2; // number so far
if (places > explaces)
badarg("format", 3, java.lang.String.valueOf(explaces));
if (places < explaces) { // need to insert zeros
newa = new char[(a.length + explaces) - places];
java.lang.System.arraycopy(a, 0, newa, 0, p + 2); // through E
// and sign
{
int $15 = explaces - places;
i = p + 2;
for (; $15 > 0; $15--, i++) {
newa[i] = '0';
}
}/* i */
java.lang.System.arraycopy(a, p + 2, newa, i, places); // remainder
// of
// exponent
a = newa;
}
// [if places=explaces then it's just the right length]
}
}
return new java.lang.String(a);
}
/**
* Returns the hashcode for this BigDecimal
. This hashcode is suitable for use by the
* java.util.Hashtable
class.
*
* Note that two BigDecimal
objects are only guaranteed to produce the same hashcode if they are
* exactly equal (that is, the String
representations of the BigDecimal
numbers are
* identical -- they have the same characters in the same sequence).
*
* @return An int
that is the hashcode for this
.
* @stable ICU 2.0
*/
@Override
public int hashCode() {
// Maybe calculate ourselves, later. If so, note that there can be
// more than one internal representation for a given toString() result.
return this.toString().hashCode();
}
/**
* Converts this BigDecimal
to an int
. If the BigDecimal
has a non-zero
* decimal part it is discarded. If the BigDecimal
is out of the possible range for an int
* (32-bit signed integer) result then only the low-order 32 bits are used. (That is, the number may be
* decapitated.) To avoid unexpected errors when these conditions occur, use the {@link #intValueExact}
* method.
*
* @return An int
converted from this
, truncated and decapitated if necessary.
* @stable ICU 2.0
*/
@Override
public int intValue() {
return toBigInteger().intValue();
}
/**
* Converts this BigDecimal
to an int
. If the BigDecimal
has a non-zero
* decimal part or is out of the possible range for an int
(32-bit signed integer) result then an
* ArithmeticException
is thrown.
*
* @return An int
equal in value to this
.
* @throws ArithmeticException if this
has a non-zero decimal part, or will not fit in an int
.
* @stable ICU 2.0
*/
public int intValueExact() {
int lodigit;
int useexp = 0;
int result;
int i = 0;
int topdig = 0;
// This does not use longValueExact() as the latter can be much
// slower.
// intcheck (from pow) relies on this to check decimal part
if (ind == iszero)
return 0; // easy, and quite common
/* test and drop any trailing decimal part */
lodigit = mant.length - 1;
if (exp < 0) {
lodigit = lodigit + exp; // reduces by -(-exp)
/* all decimal places must be 0 */
if ((!(allzero(mant, lodigit + 1))))
throw new java.lang.ArithmeticException("Decimal part non-zero:" + " " + this.toString());
if (lodigit < 0)
return 0; // -1=0 */
if ((exp + lodigit) > 9) // early exit
throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
useexp = exp;
}
/* convert the mantissa to binary, inline for speed */
result = 0;
{
int $16 = lodigit + useexp;
i = 0;
for (; i <= $16; i++) {
result = result * 10;
if (i <= lodigit)
result = result + mant[i];
}
}/* i */
/* Now, if the risky length, check for overflow */
if ((lodigit + useexp) == 9) {
// note we cannot just test for -ve result, as overflow can move a
// zero into the top bit [consider 5555555555]
topdig = result / 1000000000; // get top digit, preserving sign
if (topdig != mant[0]) { // digit must match and be positive
// except in the special case ...
if (result == java.lang.Integer.MIN_VALUE) // looks like the special
if (ind == isneg) // really was negative
if (mant[0] == 2)
return result; // really had top digit 2
throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
}
}
/* Looks good */
if (ind == ispos)
return result;
return -result;
}
/**
* Converts this BigDecimal
to a long
. If the BigDecimal
has a non-zero
* decimal part it is discarded. If the BigDecimal
is out of the possible range for a long
* (64-bit signed integer) result then only the low-order 64 bits are used. (That is, the number may be
* decapitated.) To avoid unexpected errors when these conditions occur, use the {@link #longValueExact}
* method.
*
* @return A long
converted from this
, truncated and decapitated if necessary.
* @stable ICU 2.0
*/
@Override
public long longValue() {
return toBigInteger().longValue();
}
/**
* Converts this BigDecimal
to a long
. If the BigDecimal
has a non-zero
* decimal part or is out of the possible range for a long
(64-bit signed integer) result then an
* ArithmeticException
is thrown.
*
* @return A long
equal in value to this
.
* @throws ArithmeticException if this
has a non-zero decimal part, or will not fit in a long
.
* @stable ICU 2.0
*/
public long longValueExact() {
int lodigit;
int cstart = 0;
int useexp = 0;
long result;
int i = 0;
long topdig = 0;
// Identical to intValueExact except for result=long, and exp>=20 test
if (ind == 0)
return 0; // easy, and quite common
lodigit = mant.length - 1; // last included digit
if (exp < 0) {
lodigit = lodigit + exp; // -(-exp)
/* all decimal places must be 0 */
if (lodigit < 0)
cstart = 0;
else
cstart = lodigit + 1;
if ((!(allzero(mant, cstart))))
throw new java.lang.ArithmeticException("Decimal part non-zero:" + " " + this.toString());
if (lodigit < 0)
return 0; // -1=0 */
if ((exp + mant.length) > 18) // early exit
throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
useexp = exp;
}
/* convert the mantissa to binary, inline for speed */
// note that we could safely use the 'test for wrap to negative'
// algorithm here, but instead we parallel the intValueExact
// algorithm for ease of checking and maintenance.
result = 0;
{
int $17 = lodigit + useexp;
i = 0;
for (; i <= $17; i++) {
result = result * 10;
if (i <= lodigit)
result = result + mant[i];
}
}/* i */
/* Now, if the risky length, check for overflow */
if ((lodigit + useexp) == 18) {
topdig = result / 1000000000000000000L; // get top digit, preserving sign
if (topdig != mant[0]) { // digit must match and be positive
// except in the special case ...
if (result == java.lang.Long.MIN_VALUE) // looks like the special
if (ind == isneg) // really was negative
if (mant[0] == 9)
return result; // really had top digit 9
throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
}
}
/* Looks good */
if (ind == ispos)
return result;
return -result;
}
/**
* Returns a plain BigDecimal
whose decimal point has been moved to the left by a specified number of
* positions. The parameter, n
, specifies the number of positions to move the decimal point. That is,
* if n
is 0 or positive, the number returned is given by:
*
* this.multiply(TEN.pow(new BigDecimal(-n)))
*
* n
may be negative, in which case the method returns the same result as movePointRight(-n)
*
.
*
* @param n The int
specifying the number of places to move the decimal point leftwards.
* @return A BigDecimal
derived from this
, with the decimal point moved n
* places to the left.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal movePointLeft(int n) {
com.ibm.icu.math.BigDecimal res;
// very little point in optimizing for shift of 0
res = clone(this);
res.exp = res.exp - n;
return res.finish(plainMC, false); // finish sets form and checks exponent
}
/**
* Returns a plain BigDecimal
whose decimal point has been moved to the right by a specified number of
* positions. The parameter, n
, specifies the number of positions to move the decimal point. That is,
* if n
is 0 or positive, the number returned is given by:
*
* this.multiply(TEN.pow(new BigDecimal(n)))
*
* n
may be negative, in which case the method returns the same result as movePointLeft(-n)
*
.
*
* @param n The int
specifying the number of places to move the decimal point rightwards.
* @return A BigDecimal
derived from this
, with the decimal point moved n
* places to the right.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal movePointRight(int n) {
com.ibm.icu.math.BigDecimal res;
res = clone(this);
res.exp = res.exp + n;
return res.finish(plainMC, false);
}
/**
* Returns the scale of this BigDecimal
. Returns a non-negative int
which is the scale of
* the number. The scale is the number of digits in the decimal part of the number if the number were formatted
* without exponential notation.
*
* @return An int
whose value is the scale of this BigDecimal
.
* @stable ICU 2.0
*/
public int scale() {
if (exp >= 0)
return 0; // scale can never be negative
return -exp;
}
/**
* Returns a plain BigDecimal
with a given scale.
*
* If the given scale (which must be zero or positive) is the same as or greater than the length of the decimal part
* (the scale) of this BigDecimal
then trailing zeros will be added to the decimal part as necessary.
*
* If the given scale is less than the length of the decimal part (the scale) of this BigDecimal
then
* trailing digits will be removed, and in this case an ArithmeticException
is thrown if any discarded
* digits are non-zero.
*
* The same as {@link #setScale(int, int)}, where the first parameter is the scale, and the second is
* MathContext.ROUND_UNNECESSARY
.
*
* @param scale The int
specifying the scale of the resulting BigDecimal
.
* @return A plain BigDecimal
with the given scale.
* @throws ArithmeticException if scale
is negative.
* @throws ArithmeticException if reducing scale would discard non-zero digits.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal setScale(int scale) {
return setScale(scale, ROUND_UNNECESSARY);
}
/**
* Returns a plain BigDecimal
with a given scale.
*
* If the given scale (which must be zero or positive) is the same as or greater than the length of the decimal part
* (the scale) of this BigDecimal
then trailing zeros will be added to the decimal part as necessary.
*
* If the given scale is less than the length of the decimal part (the scale) of this BigDecimal
then
* trailing digits will be removed, and the rounding mode given by the second parameter is used to determine if the
* remaining digits are affected by a carry. In this case, an IllegalArgumentException
is thrown if
* round
is not a valid rounding mode.
*
* If round
is MathContext.ROUND_UNNECESSARY
, an ArithmeticException
is
* thrown if any discarded digits are non-zero.
*
* @param scale The int
specifying the scale of the resulting BigDecimal
.
* @param round The int
rounding mode to be used for the division (see the {@link MathContext} class).
* @return A plain BigDecimal
with the given scale.
* @throws IllegalArgumentException if round
is not a valid rounding mode.
* @throws ArithmeticException if scale
is negative.
* @throws ArithmeticException if round
is MathContext.ROUND_UNNECESSARY
, and reducing scale would discard
* non-zero digits.
* @stable ICU 2.0
*/
public com.ibm.icu.math.BigDecimal setScale(int scale, int round) {
int ourscale;
com.ibm.icu.math.BigDecimal res;
int padding = 0;
int newlen = 0;
// at present this naughtily only checks the round value if it is
// needed (used), for speed
ourscale = this.scale();
if (ourscale == scale) // already correct scale
if (this.form == com.ibm.icu.math.MathContext.PLAIN) // .. and form
return this;
res = clone(this); // need copy
if (ourscale <= scale) { // simply zero-padding/changing form
// if ourscale is 0 we may have lots of 0s to add
if (ourscale == 0)
padding = res.exp + scale;
else
padding = scale - ourscale;
res.mant = extend(res.mant, res.mant.length + padding);
res.exp = -scale; // as requested
} else {/* ourscale>scale: shortening, probably */
if (scale < 0)
throw new java.lang.ArithmeticException("Negative scale:" + " " + scale);
// [round() will raise exception if invalid round]
newlen = res.mant.length - ((ourscale - scale)); // [<=0 is OK]
res = res.round(newlen, round); // round to required length
// This could have shifted left if round (say) 0.9->1[.0]
// Repair if so by adding a zero and reducing exponent
if (res.exp != -scale) {
res.mant = extend(res.mant, res.mant.length + 1);
res.exp = res.exp - 1;
}
}
res.form = (byte) com.ibm.icu.math.MathContext.PLAIN; // by definition
return res;
}
/**
* Converts this BigDecimal
to a short
. If the BigDecimal
has a non-zero
* decimal part or is out of the possible range for a short
(16-bit signed integer) result then an
* ArithmeticException
is thrown.
*
* @return A short
equal in value to this
.
* @throws ArithmeticException if this
has a non-zero decimal part, or will not fit in a short
.
* @stable ICU 2.0
*/
public short shortValueExact() {
int num;
num = this.intValueExact(); // will check decimal part too
if ((num > 32767) | (num < (-32768)))
throw new java.lang.ArithmeticException("Conversion overflow:" + " " + this.toString());
return (short) num;
}
/**
* Returns the sign of this BigDecimal
, as an int
. This returns the signum function
* value that represents the sign of this BigDecimal
. That is, -1 if the BigDecimal
is
* negative, 0 if it is numerically equal to zero, or 1 if it is positive.
*
* @return An int
which is -1 if the BigDecimal
is negative, 0 if it is numerically equal
* to zero, or 1 if it is positive.
* @stable ICU 2.0
*/
public int signum() {
return this.ind; // [note this assumes values for ind.]
}
/**
* Converts this BigDecimal
to a java.math.BigDecimal
.
*
* This is an exact conversion; the result is the same as if the BigDecimal
were formatted as a plain
* number without any rounding or exponent and then the java.math.BigDecimal(java.lang.String)
* constructor were used to construct the result.
*
* (Note: this method is provided only in the com.ibm.icu.math
version of the BigDecimal class. It
* would not be present in a java.math
version.)
*
* @return The java.math.BigDecimal
equal in value to this BigDecimal
.
* @stable ICU 2.0
*/
public java.math.BigDecimal toBigDecimal() {
return new java.math.BigDecimal(this.unscaledValue(), this.scale());
}
/**
* Converts this BigDecimal
to a java.math.BigInteger
.
*
* Any decimal part is truncated (discarded). If an exception is desired should the decimal part be non-zero, use
* {@link #toBigIntegerExact()}.
*
* @return The java.math.BigInteger
equal in value to the integer part of this BigDecimal
.
* @stable ICU 2.0
*/
public java.math.BigInteger toBigInteger() {
com.ibm.icu.math.BigDecimal res = null;
int newlen = 0;
byte newmant[] = null;
{/* select */
if ((exp >= 0) & (form == com.ibm.icu.math.MathContext.PLAIN))
res = this; // can layout simply
else if (exp >= 0) {
res = clone(this); // safe copy
res.form = (byte) com.ibm.icu.math.MathContext.PLAIN; // .. and request PLAIN
} else {
{ // exp<0; scale to be truncated
// we could use divideInteger, but we may as well be quicker
if (-this.exp >= this.mant.length)
res = ZERO; // all blows away
else {
res = clone(this); // safe copy
newlen = res.mant.length + res.exp;
newmant = new byte[newlen]; // [shorter]
java.lang.System.arraycopy(res.mant, 0, newmant, 0,
newlen);
res.mant = newmant;
res.form = (byte) com.ibm.icu.math.MathContext.PLAIN;
res.exp = 0;
}
}
}
}
return new BigInteger(new java.lang.String(res.layout()));
}
/**
* Converts this BigDecimal
to a java.math.BigInteger
.
*
* An exception is thrown if the decimal part (if any) is non-zero.
*
* @return The java.math.BigInteger
equal in value to the integer part of this BigDecimal
.
* @throws ArithmeticException if this
has a non-zero decimal part.
* @stable ICU 2.0
*/
public java.math.BigInteger toBigIntegerExact() {
/* test any trailing decimal part */
if (exp < 0) { // possible decimal part
/* all decimal places must be 0; note exp<0 */
if ((!(allzero(mant, mant.length + exp))))
throw new java.lang.ArithmeticException("Decimal part non-zero:" + " " + this.toString());
}
return toBigInteger();
}
/**
* Returns the BigDecimal
as a character array. The result of this method is the same as using the
* sequence toString().toCharArray()
, but avoids creating the intermediate String
and
* char[]
objects.
*
* @return The char[]
array corresponding to this BigDecimal
.
* @stable ICU 2.0
*/
public char[] toCharArray() {
return layout();
}
/**
* Returns the BigDecimal
as a String
. This returns a String
that exactly
* represents this BigDecimal
, as defined in the decimal documentation (see {@link BigDecimal class
* header}).
*
* By definition, using the {@link #BigDecimal(String)} constructor on the result String
will create a
* BigDecimal
that is exactly equal to the original BigDecimal
.
*
* @return The String
exactly corresponding to this BigDecimal
.
* @see #format(int, int)
* @see #format(int, int, int, int, int, int)
* @see #toCharArray()
* @stable ICU 2.0
*/
@Override
public java.lang.String toString() {
return new java.lang.String(layout());
}
/**
* Returns the number as a BigInteger
after removing the scale. That is, the number is expressed as a
* plain number, any decimal point is then removed (retaining the digits of any decimal part), and the result is
* then converted to a BigInteger
.
*
* @return The java.math.BigInteger
equal in value to this BigDecimal
multiplied by ten to
* the power of this.scale()
.
* @stable ICU 2.0
*/
public java.math.BigInteger unscaledValue() {
com.ibm.icu.math.BigDecimal res = null;
if (exp >= 0)
res = this;
else {
res = clone(this); // safe copy
res.exp = 0; // drop scale
}
return res.toBigInteger();
}
/**
* Translates a double
to a BigDecimal
.
*
* Returns a BigDecimal
which is the decimal representation of the 64-bit signed binary floating point
* parameter. If the parameter is infinite, or is not a number (NaN), a NumberFormatException
is
* thrown.
*
* The number is constructed as though num
had been converted to a String
using the
* Double.toString()
method and the {@link #BigDecimal(java.lang.String)} constructor had then been used.
* This is typically not an exact conversion.
*
* @param dub The double
to be translated.
* @return The BigDecimal
equal in value to dub
.
* @throws NumberFormatException if the parameter is infinite or not a number.
* @stable ICU 2.0
*/
public static com.ibm.icu.math.BigDecimal valueOf(double dub) {
// Reminder: a zero double returns '0.0', so we cannot fastpath to
// use the constant ZERO. This might be important enough to justify
// a factory approach, a cache, or a few private constants, later.
return new com.ibm.icu.math.BigDecimal((new java.lang.Double(dub)).toString());
}
/**
* Translates a long
to a BigDecimal
. That is, returns a plain BigDecimal
* whose value is equal to the given long
.
*
* @param lint The long
to be translated.
* @return The BigDecimal
equal in value to lint
.
* @stable ICU 2.0
*/
public static com.ibm.icu.math.BigDecimal valueOf(long lint) {
return valueOf(lint, 0);
}
/**
* Translates a long
to a BigDecimal
with a given scale. That is, returns a plain
* BigDecimal
whose unscaled value is equal to the given long
, adjusted by the second parameter,
* scale
.
*
* The result is given by:
*
* (new BigDecimal(lint)).divide(TEN.pow(new BigDecimal(scale)))
*
* A NumberFormatException
is thrown if scale
is negative.
*
* @param lint The long
to be translated.
* @param scale The int
scale to be applied.
* @return The BigDecimal
equal in value to lint
.
* @throws NumberFormatException if the scale is negative.
* @stable ICU 2.0
*/
public static com.ibm.icu.math.BigDecimal valueOf(long lint, int scale) {
com.ibm.icu.math.BigDecimal res = null;
{/* select */
if (lint == 0)
res = ZERO;
else if (lint == 1)
res = ONE;
else if (lint == 10)
res = TEN;
else {
res = new com.ibm.icu.math.BigDecimal(lint);
}
}
if (scale == 0)
return res;
if (scale < 0)
throw new java.lang.NumberFormatException("Negative scale:" + " " + scale);
res = clone(res); // safe copy [do not mutate]
res.exp = -scale; // exponent is -scale
return res;
}
/* ---------------------------------------------------------------- */
/* Private methods */
/* ---------------------------------------------------------------- */
/*
* Return char array value of a BigDecimal (conversion from BigDecimal to laid-out canonical char array).
* The mantissa will either already have been rounded (following an operation) or will be of length appropriate
* (in the case of construction from an int, for example).
We must not alter the mantissa, here.
'form'
* describes whether we are to use exponential notation (and if so, which), or if we are to lay out as a plain/pure
* numeric.
*/
private char[] layout() {
char cmant[];
int i = 0;
StringBuilder sb = null;
int euse = 0;
int sig = 0;
char csign = 0;
char rec[] = null;
int needsign;
int mag;
int len = 0;
cmant = new char[mant.length]; // copy byte[] to a char[]
{
int $18 = mant.length;
i = 0;
for (; $18 > 0; $18--, i++) {
cmant[i] = (char) (mant[i] + (('0')));
}
}/* i */
if (form != com.ibm.icu.math.MathContext.PLAIN) {/* exponential notation needed */
sb = new StringBuilder(cmant.length + 15); // -x.xxxE+999999999
if (ind == isneg)
sb.append('-');
euse = (exp + cmant.length) - 1; // exponent to use
/* setup sig=significant digits and copy to result */
if (form == com.ibm.icu.math.MathContext.SCIENTIFIC) { // [default]
sb.append(cmant[0]); // significant character
if (cmant.length > 1) // have decimal part
sb.append('.').append(cmant, 1, cmant.length - 1);
} else {
do {
sig = euse % 3; // common
if (sig < 0)
sig = 3 + sig; // negative exponent
euse = euse - sig;
sig++;
if (sig >= cmant.length) { // zero padding may be needed
sb.append(cmant, 0, cmant.length);
{
int $19 = sig - cmant.length;
for (; $19 > 0; $19--) {
sb.append('0');
}
}
} else { // decimal point needed
sb.append(cmant, 0, sig).append('.').append(cmant, sig, cmant.length - sig);
}
} while (false);
}/* engineering */
if (euse != 0) {
if (euse < 0) {
csign = '-';
euse = -euse;
} else
csign = '+';
sb.append('E').append(csign).append(euse);
}
rec = new char[sb.length()];
int srcEnd = sb.length();
if (0 != srcEnd) {
sb.getChars(0, srcEnd, rec, 0);
}
return rec;
}
/* Here for non-exponential (plain) notation */
if (exp == 0) {/* easy */
if (ind >= 0)
return cmant; // non-negative integer
rec = new char[cmant.length + 1];
rec[0] = '-';
java.lang.System.arraycopy(cmant, 0, rec, 1, cmant.length);
return rec;
}
/* Need a '.' and/or some zeros */
needsign = (ind == isneg) ? 1 : 0; // space for sign? 0 or 1
/*
* MAG is the position of the point in the mantissa (index of the character it follows)
*/
mag = exp + cmant.length;
if (mag < 1) {/* 0.00xxxx form */
len = (needsign + 2) - exp; // needsign+2+(-mag)+cmant.length
rec = new char[len];
if (needsign != 0)
rec[0] = '-';
rec[needsign] = '0';
rec[needsign + 1] = '.';
{
int $20 = -mag;
i = needsign + 2;
for (; $20 > 0; $20--, i++) { // maybe none
rec[i] = '0';
}
}/* i */
java.lang.System.arraycopy(cmant, 0, rec, (needsign + 2) - mag,
cmant.length);
return rec;
}
if (mag > cmant.length) {/* xxxx0000 form */
len = needsign + mag;
rec = new char[len];
if (needsign != 0)
rec[0] = '-';
java.lang.System.arraycopy(cmant, 0, rec, needsign, cmant.length);
{
int $21 = mag - cmant.length;
i = needsign + cmant.length;
for (; $21 > 0; $21--, i++) { // never 0
rec[i] = '0';
}
}/* i */
return rec;
}
/* decimal point is in the middle of the mantissa */
len = (needsign + 1) + cmant.length;
rec = new char[len];
if (needsign != 0)
rec[0] = '-';
java.lang.System.arraycopy(cmant, 0, rec, needsign, mag);
rec[needsign + mag] = '.';
java.lang.System.arraycopy(cmant, mag, rec, (needsign + mag) + 1,
cmant.length - mag);
return rec;
}
/*
* Checks a BigDecimal argument to ensure it's a true integer in a given range. If OK, returns it as an
* int.
*/
// [currently only used by pow]
private int intcheck(int min, int max) {
int i;
i = this.intValueExact(); // [checks for non-0 decimal part]
// Use same message as though intValueExact failed due to size
if ((i < min) | (i > max))
throw new java.lang.ArithmeticException("Conversion overflow:" + " " + i);
return i;
}
/* Carry out division operations. */
/*
* Arg1 is operation code: D=divide, I=integer divide, R=remainder Arg2 is the rhs. Arg3 is the context. Arg4 is
* explicit scale iff code='D' or 'I' (-1 if none).
*
* Underlying algorithm (complications for Remainder function and scaled division are omitted for clarity):
*
* Test for x/0 and then 0/x Exp =Exp1 - Exp2 Exp =Exp +len(var1) -len(var2) Sign=Sign1 Sign2 Pad accumulator (Var1)
* to double-length with 0's (pad1) Pad Var2 to same length as Var1 B2B=1st two digits of var2, +1 to allow for
* roundup have=0 Do until (have=digits+1 OR residue=0) if exp<0 then if integer divide/residue then leave
* this_digit=0 Do forever compare numbers if <0 then leave inner_loop if =0 then (- quick exit without subtract -)
* do this_digit=this_digit+1; output this_digit leave outer_loop; end Compare lengths of numbers (mantissae): If
* same then CA=first_digit_of_Var1 else CA=first_two_digits_of_Var1 mult=ca10/b2b -- Good and safe guess at divisor
* if mult=0 then mult=1 this_digit=this_digit+mult subtract end inner_loop if have\=0 | this_digit\=0 then do
* output this_digit have=have+1; end var2=var2/10 exp=exp-1 end outer_loop exp=exp+1 -- set the proper exponent if
* have=0 then generate answer=0 Return to FINISHED Result defined by MATHV1
*
* For extended commentary, see DMSRCN.
*/
private com.ibm.icu.math.BigDecimal dodivide(char code, com.ibm.icu.math.BigDecimal rhs,
com.ibm.icu.math.MathContext set, int scale) {
com.ibm.icu.math.BigDecimal lhs;
int reqdig;
int newexp;
com.ibm.icu.math.BigDecimal res;
int newlen;
byte var1[];
int var1len;
byte var2[];
int var2len;
int b2b;
int have;
int thisdigit = 0;
int i = 0;
byte v2 = 0;
int ba = 0;
int mult = 0;
int start = 0;
int padding = 0;
int d = 0;
byte newvar1[] = null;
byte lasthave = 0;
int actdig = 0;
byte newmant[] = null;
if (set.lostDigits)
checkdigits(rhs, set.digits);
lhs = this; // name for clarity
// [note we must have checked lostDigits before the following checks]
if (rhs.ind == 0)
throw new java.lang.ArithmeticException("Divide by 0"); // includes 0/0
if (lhs.ind == 0) { // 0/x => 0 [possibly with .0s]
if (set.form != com.ibm.icu.math.MathContext.PLAIN)
return ZERO;
if (scale == (-1))
return lhs;
return lhs.setScale(scale);
}
/* Prepare numbers according to BigDecimal rules */
reqdig = set.digits; // local copy (heavily used)
if (reqdig > 0) {
if (lhs.mant.length > reqdig)
lhs = clone(lhs).round(set);
if (rhs.mant.length > reqdig)
rhs = clone(rhs).round(set);
} else {/* scaled divide */
if (scale == (-1))
scale = lhs.scale();
// set reqdig to be at least large enough for the computation
reqdig = lhs.mant.length; // base length
// next line handles both positive lhs.exp and also scale mismatch
if (scale != -lhs.exp)
reqdig = (reqdig + scale) + lhs.exp;
reqdig = (reqdig - ((rhs.mant.length - 1))) - rhs.exp; // reduce by RHS effect
if (reqdig < lhs.mant.length)
reqdig = lhs.mant.length; // clamp
if (reqdig < rhs.mant.length)
reqdig = rhs.mant.length; // ..
}
/* precalculate exponent */
newexp = ((lhs.exp - rhs.exp) + lhs.mant.length) - rhs.mant.length;
/* If new exponent -ve, then some quick exits are possible */
if (newexp < 0)
if (code != 'D') {
if (code == 'I')
return ZERO; // easy - no integer part
/* Must be 'R'; remainder is [finished clone of] input value */
return clone(lhs).finish(set, false);
}
/* We need slow division */
res = new com.ibm.icu.math.BigDecimal(); // where we'll build result
res.ind = (byte) (lhs.ind * rhs.ind); // final sign (for D/I)
res.exp = newexp; // initial exponent (for D/I)
res.mant = new byte[reqdig + 1]; // where build the result
/* Now [virtually pad the mantissae with trailing zeros */
// Also copy the LHS, which will be our working array
newlen = (reqdig + reqdig) + 1;
var1 = extend(lhs.mant, newlen); // always makes longer, so new safe array
var1len = newlen; // [remaining digits are 0]
var2 = rhs.mant;
var2len = newlen;
/* Calculate first two digits of rhs (var2), +1 for later estimations */
b2b = (var2[0] * 10) + 1;
if (var2.length > 1)
b2b = b2b + var2[1];
/* start the long-division loops */
have = 0;
{
outer: for (;;) {
thisdigit = 0;
/* find the next digit */
{
inner: for (;;) {
if (var1len < var2len)
break inner; // V1 too low
if (var1len == var2len) { // compare needed
{
compare: do { // comparison
{
int $22 = var1len;
i = 0;
for (; $22 > 0; $22--, i++) {
// var1len is always <= var1.length
if (i < var2.length)
v2 = var2[i];
else
v2 = (byte) 0;
if (var1[i] < v2)
break inner; // V1 too low
if (var1[i] > v2)
break compare; // OK to subtract
}
}/* i */
/*
* reach here if lhs and rhs are identical; subtraction will increase digit by one,
* and the residue will be 0 so we are done; leave the loop with residue set to 0
* (in case code is 'R' or ROUND_UNNECESSARY or a ROUND_HALF_xxxx is being checked)
*/
thisdigit++;
res.mant[have] = (byte) thisdigit;
have++;
var1[0] = (byte) 0; // residue to 0 [this is all we'll test]
// var1len=1 -- [optimized out]
break outer;
} while (false);
}/* compare */
/* prepare for subtraction. Estimate BA (lengths the same) */
ba = var1[0]; // use only first digit
} // lengths the same
else {/* lhs longer than rhs */
/* use first two digits for estimate */
ba = var1[0] * 10;
if (var1len > 1)
ba = ba + var1[1];
}
/* subtraction needed; V1>=V2 */
mult = (ba * 10) / b2b;
if (mult == 0)
mult = 1;
thisdigit = thisdigit + mult;
// subtract; var1 reusable
var1 = byteaddsub(var1, var1len, var2, var2len, -mult, true);
if (var1[0] != 0)
continue inner; // maybe another subtract needed
/*
* V1 now probably has leading zeros, remove leading 0's and try again. (It could be longer than
* V2)
*/
{
int $23 = var1len - 2;
start = 0;
start: for (; start <= $23; start++) {
if (var1[start] != 0)
break start;
var1len--;
}
}/* start */
if (start == 0)
continue inner;
// shift left
java.lang.System.arraycopy(var1, start, var1, 0, var1len);
}
}/* inner */
/* We have the next digit */
if ((have != 0) | (thisdigit != 0)) { // put the digit we got
res.mant[have] = (byte) thisdigit;
have++;
if (have == (reqdig + 1))
break outer; // we have all we need
if (var1[0] == 0)
break outer; // residue now 0
}
/* can leave now if a scaled divide and exponent is small enough */
if (scale >= 0)
if (-res.exp > scale)
break outer;
/* can leave now if not Divide and no integer part left */
if (code != 'D')
if (res.exp <= 0)
break outer;
res.exp = res.exp - 1; // reduce the exponent
/*
* to get here, V1 is less than V2, so divide V2 by 10 and go for the next digit
*/
var2len--;
}
}/* outer */
/* here when we have finished dividing, for some reason */
// have is the number of digits we collected in res.mant
if (have == 0)
have = 1; // res.mant[0] is 0; we always want a digit
if ((code == 'I') | (code == 'R')) {/* check for integer overflow needed */
if ((have + res.exp) > reqdig)
throw new java.lang.ArithmeticException("Integer overflow");
if (code == 'R') {
do {
/* We were doing Remainder -- return the residue */
if (res.mant[0] == 0) // no integer part was found
return clone(lhs).finish(set, false); // .. so return lhs, canonical
if (var1[0] == 0)
return ZERO; // simple 0 residue
res.ind = lhs.ind; // sign is always as LHS
/*
* Calculate the exponent by subtracting the number of padding zeros we added and adding the
* original exponent
*/
padding = ((reqdig + reqdig) + 1) - lhs.mant.length;
res.exp = (res.exp - padding) + lhs.exp;
/*
* strip insignificant padding zeros from residue, and create/copy the resulting mantissa if need be
*/
d = var1len;
{
i = d - 1;
i: for (; i >= 1; i--) {
if (!((res.exp < lhs.exp) & (res.exp < rhs.exp)))
break;
if (var1[i] != 0)
break i;
d--;
res.exp = res.exp + 1;
}
}/* i */
if (d < var1.length) {/* need to reduce */
newvar1 = new byte[d];
java.lang.System.arraycopy(var1, 0, newvar1, 0, d); // shorten
var1 = newvar1;
}
res.mant = var1;
return res.finish(set, false);
} while (false);
}/* remainder */
}
else {/* 'D' -- no overflow check needed */
// If there was a residue then bump the final digit (iff 0 or 5)
// so that the residue is visible for ROUND_UP, ROUND_HALF_xxx and
// ROUND_UNNECESSARY checks (etc.) later.
// [if we finished early, the residue will be 0]
if (var1[0] != 0) { // residue not 0
lasthave = res.mant[have - 1];
if (((lasthave % 5)) == 0)
res.mant[have - 1] = (byte) (lasthave + 1);
}
}
/* Here for Divide or Integer Divide */
// handle scaled results first ['I' always scale 0, optional for 'D']
if (scale >= 0) {
do {
// say 'scale have res.exp len' scale have res.exp res.mant.length
if (have != res.mant.length)
// already padded with 0's, so just adjust exponent
res.exp = res.exp - ((res.mant.length - have));
// calculate number of digits we really want [may be 0]
actdig = res.mant.length - (-res.exp - scale);
res.round(actdig, set.roundingMode); // round to desired length
// This could have shifted left if round (say) 0.9->1[.0]
// Repair if so by adding a zero and reducing exponent
if (res.exp != -scale) {
res.mant = extend(res.mant, res.mant.length + 1);
res.exp = res.exp - 1;
}
return res.finish(set, true); // [strip if not PLAIN]
} while (false);
}/* scaled */
// reach here only if a non-scaled
if (have == res.mant.length) { // got digits+1 digits
res.round(set);
have = reqdig;
} else {/* have<=reqdig */
if (res.mant[0] == 0)
return ZERO; // fastpath
// make the mantissa truly just 'have' long
// [we could let finish do this, during strip, if we adjusted
// the exponent; however, truncation avoids the strip loop]
newmant = new byte[have]; // shorten
java.lang.System.arraycopy(res.mant, 0, newmant, 0, have);
res.mant = newmant;
}
return res.finish(set, true);
}
/* Report a conversion exception. */
private void bad(char s[]) {
throw new java.lang.NumberFormatException("Not a number:" + " " + java.lang.String.valueOf(s));
}
/*
* Report a bad argument to a method. Arg1 is method name Arg2 is argument position Arg3 is what was
* found
*/
private void badarg(java.lang.String name, int pos, java.lang.String value) {
throw new java.lang.IllegalArgumentException("Bad argument" + " " + pos + " " + "to" + " " + name + ":" + " "
+ value);
}
/*
* Extend byte array to given length, padding with 0s. If no extension is required then return the same
* array.
*
* Arg1 is the source byte array Arg2 is the new length (longer)
*/
private static final byte[] extend(byte inarr[], int newlen) {
byte newarr[];
if (inarr.length == newlen)
return inarr;
newarr = new byte[newlen];
java.lang.System.arraycopy(inarr, 0, newarr, 0, inarr.length);
// 0 padding is carried out by the JVM on allocation initialization
return newarr;
}
/*
* Add or subtract two >=0 integers in byte arrays This routine performs the calculation:
C=A+(BM)
*
Where M is in the range -9 through +9 If M<0 then A>=B must be true, so the result is always
* non-negative.
*
* Leading zeros are not removed after a subtraction. The result is either the same length as the longer of A and B,
* or 1 longer than that (if a carry occurred).
*
* A is not altered unless Arg6 is 1. B is never altered.
*
* Arg1 is A Arg2 is A length to use (if longer than A, pad with 0's) Arg3 is B Arg4 is B length to use (if longer
* than B, pad with 0's) Arg5 is M, the multiplier Arg6 is 1 if A can be used to build the result (if it fits)
*
* This routine is severely performance-critical;any change here must be measured (timed) to assure no performance
* degradation.
*/
// 1996.02.20 -- enhanced version of DMSRCN algorithm (1981)
// 1997.10.05 -- changed to byte arrays (from char arrays)
// 1998.07.01 -- changed to allow destructive reuse of LHS
// 1998.07.01 -- changed to allow virtual lengths for the arrays
// 1998.12.29 -- use lookaside for digit/carry calculation
// 1999.08.07 -- avoid multiply when mult=1, and make db an int
// 1999.12.22 -- special case m=-1, also drop 0 special case
private static final byte[] byteaddsub(byte a[], int avlen, byte b[], int bvlen, int m, boolean reuse) {
int alength;
int blength;
int ap;
int bp;
int maxarr;
byte reb[];
boolean quickm;
int digit;
int op = 0;
int dp90 = 0;
byte newarr[];
int i = 0;
// We'll usually be right if we assume no carry
alength = a.length; // physical lengths
blength = b.length; // ..
ap = avlen - 1; // -> final (rightmost) digit
bp = bvlen - 1; // ..
maxarr = bp;
if (maxarr < ap)
maxarr = ap;
reb = null; // result byte array
if (reuse)
if ((maxarr + 1) == alength)
reb = a; // OK to reuse A
if (reb == null)
reb = new byte[maxarr + 1]; // need new array
quickm = false; // 1 if no multiply needed
if (m == 1)
quickm = true; // most common
else if (m == (-1))
quickm = true; // also common
digit = 0; // digit, with carry or borrow
{
op = maxarr;
op: for (; op >= 0; op--) {
if (ap >= 0) {
if (ap < alength)
digit = digit + a[ap]; // within A
ap--;
}
if (bp >= 0) {
if (bp < blength) { // within B
if (quickm) {
if (m > 0)
digit = digit + b[bp]; // most common
else
digit = digit - b[bp]; // also common
} else
digit = digit + (b[bp] * m);
}
bp--;
}
/* result so far (digit) could be -90 through 99 */
if (digit < 10)
if (digit >= 0) {
do { // 0-9
reb[op] = (byte) digit;
digit = 0; // no carry
continue op;
} while (false);
}/* quick */
dp90 = digit + 90;
reb[op] = bytedig[dp90]; // this digit
digit = bytecar[dp90]; // carry or borrow
}
}/* op */
if (digit == 0)
return reb; // no carry
// following line will become an Assert, later
// if digit<0 then signal ArithmeticException("internal.error ["digit"]")
/* We have carry -- need to make space for the extra digit */
newarr = null;
if (reuse)
if ((maxarr + 2) == a.length)
newarr = a; // OK to reuse A
if (newarr == null)
newarr = new byte[maxarr + 2];
newarr[0] = (byte) digit; // the carried digit ..
// .. and all the rest [use local loop for short numbers]
if (maxarr < 10) {
int $24 = maxarr + 1;
i = 0;
for (; $24 > 0; $24--, i++) {
newarr[i + 1] = reb[i];
}
}/* i */
else
java.lang.System.arraycopy(reb, 0, newarr, 1, maxarr + 1);
return newarr;
}
/*
* Initializer for digit array properties (lookaside). Returns the digit array, and initializes the
* carry array.
*/
private static final byte[] diginit() {
byte work[];
int op = 0;
int digit = 0;
work = new byte[(90 + 99) + 1];
{
op = 0;
op: for (; op <= (90 + 99); op++) {
digit = op - 90;
if (digit >= 0) {
work[op] = (byte) (digit % 10);
bytecar[op] = (byte) (digit / 10); // calculate carry
continue op;
}
// borrowing...
digit = digit + 100; // yes, this is right [consider -50]
work[op] = (byte) (digit % 10);
bytecar[op] = (byte) ((digit / 10) - 10); // calculate borrow [NB: - after %]
}
}/* op */
return work;
}
/*
* Create a copy of BigDecimal object for local use. This does NOT make a copy of the mantissa array.
*
Arg1 is the BigDecimal to clone (non-null)
*/
private static final com.ibm.icu.math.BigDecimal clone(com.ibm.icu.math.BigDecimal dec) {
com.ibm.icu.math.BigDecimal copy;
copy = new com.ibm.icu.math.BigDecimal();
copy.ind = dec.ind;
copy.exp = dec.exp;
copy.form = dec.form;
copy.mant = dec.mant;
return copy;
}
/*
* Check one or two numbers for lost digits. Arg1 is RHS (or null, if none) Arg2 is current DIGITS
* setting returns quietly or throws an exception
*/
private void checkdigits(com.ibm.icu.math.BigDecimal rhs, int dig) {
if (dig == 0)
return; // don't check if digits=0
// first check lhs...
if (this.mant.length > dig)
if ((!(allzero(this.mant, dig))))
throw new java.lang.ArithmeticException("Too many digits:" + " " + this.toString());
if (rhs == null)
return; // monadic
if (rhs.mant.length > dig)
if ((!(allzero(rhs.mant, dig))))
throw new java.lang.ArithmeticException("Too many digits:" + " " + rhs.toString());
}
/*
* Round to specified digits, if necessary. Arg1 is requested MathContext [with length and rounding
* mode] returns this, for convenience
*/
private com.ibm.icu.math.BigDecimal round(com.ibm.icu.math.MathContext set) {
return round(set.digits, set.roundingMode);
}
/*
* Round to specified digits, if necessary. Arg1 is requested length (digits to round to) [may be <=0 when
* called from format, dodivide, etc.] Arg2 is rounding mode returns this, for convenience
*
* ind and exp are adjusted, but not cleared for a mantissa of zero
*
* The length of the mantissa returned will be Arg1, except when Arg1 is 0, in which case the returned mantissa
* length will be 1.
*/
private com.ibm.icu.math.BigDecimal round(int len, int mode) {
int adjust;
int sign;
byte oldmant[];
boolean reuse = false;
byte first = 0;
int increment;
byte newmant[] = null;
adjust = mant.length - len;
if (adjust <= 0)
return this; // nowt to do
exp = exp + adjust; // exponent of result
sign = ind; // save [assumes -1, 0, 1]
oldmant = mant; // save
if (len > 0) {
// remove the unwanted digits
mant = new byte[len];
java.lang.System.arraycopy(oldmant, 0, mant, 0, len);
reuse = true; // can reuse mantissa
first = oldmant[len]; // first of discarded digits
} else {/* len<=0 */
mant = ZERO.mant;
ind = iszero;
reuse = false; // cannot reuse mantissa
if (len == 0)
first = oldmant[0];
else
first = (byte) 0; // [virtual digit]
}
// decide rounding adjustment depending on mode, sign, and discarded digits
increment = 0; // bumper
{
do {/* select */
if (mode == ROUND_HALF_UP) { // default first [most common]
if (first >= 5)
increment = sign;
} else if (mode == ROUND_UNNECESSARY) { // default for setScale()
// discarding any non-zero digits is an error
if ((!(allzero(oldmant, len))))
throw new java.lang.ArithmeticException("Rounding necessary");
} else if (mode == ROUND_HALF_DOWN) { // 0.5000 goes down
if (first > 5)
increment = sign;
else if (first == 5)
if ((!(allzero(oldmant, len + 1))))
increment = sign;
} else if (mode == ROUND_HALF_EVEN) { // 0.5000 goes down if left digit even
if (first > 5)
increment = sign;
else if (first == 5) {
if ((!(allzero(oldmant, len + 1))))
increment = sign;
else /* 0.5000 */
if ((((mant[mant.length - 1]) % 2)) != 0)
increment = sign;
}
} else if (mode == ROUND_DOWN) {
// never increment
} else if (mode == ROUND_UP) { // increment if discarded non-zero
if ((!(allzero(oldmant, len))))
increment = sign;
} else if (mode == ROUND_CEILING) { // more positive
if (sign > 0)
if ((!(allzero(oldmant, len))))
increment = sign;
} else if (mode == ROUND_FLOOR) { // more negative
if (sign < 0)
if ((!(allzero(oldmant, len))))
increment = sign;
} else {
throw new java.lang.IllegalArgumentException("Bad round value:" + " " + mode);
}
} while (false);
}/* modes */
if (increment != 0) {
do {
if (ind == iszero) {
// we must not subtract from 0, but result is trivial anyway
mant = ONE.mant;
ind = (byte) increment;
} else {
// mantissa is non-0; we can safely add or subtract 1
if (ind == isneg)
increment = -increment;
newmant = byteaddsub(mant, mant.length, ONE.mant, 1, increment, reuse);
if (newmant.length > mant.length) { // had a carry
// drop rightmost digit and raise exponent
exp++;
// mant is already the correct length
java.lang.System.arraycopy(newmant, 0, mant, 0,
mant.length);
} else
mant = newmant;
}
} while (false);
}/* bump */
// rounding can increase exponent significantly
if (exp > MaxExp)
throw new java.lang.ArithmeticException("Exponent Overflow:" + " " + exp);
return this;
}
/*
* Test if rightmost digits are all 0. Arg1 is a mantissa array to test Arg2 is the offset of first digit to
* check [may be negative; if so, digits to left are 0's] returns 1 if all the digits starting at Arg2 are 0
*
* Arg2 may be beyond array bounds, in which case 1 is returned
*/
private static final boolean allzero(byte array[], int start) {
int i = 0;
if (start < 0)
start = 0;
{
int $25 = array.length - 1;
i = start;
for (; i <= $25; i++) {
if (array[i] != 0)
return false;
}
}/* i */
return true;
}
/*
* Carry out final checks and canonicalization This finishes off the current number by: 1. Rounding if
* necessary (NB: length includes leading zeros) 2. Stripping trailing zeros (if requested and \PLAIN) 3. Stripping
* leading zeros (always) 4. Selecting exponential notation (if required) 5. Converting a zero result to just '0'
* (if \PLAIN) In practice, these operations overlap and share code. It always sets form.
Arg1 is requested
* MathContext (length to round to, trigger, and FORM) Arg2 is 1 if trailing insignificant zeros should be removed
* after round (for division, etc.), provided that set.form isn't PLAIN. returns this, for convenience
*/
private com.ibm.icu.math.BigDecimal finish(com.ibm.icu.math.MathContext set, boolean strip) {
int d = 0;
int i = 0;
byte newmant[] = null;
int mag = 0;
int sig = 0;
/* Round if mantissa too long and digits requested */
if (set.digits != 0)
if (this.mant.length > set.digits)
this.round(set);
/*
* If strip requested (and standard formatting), remove insignificant trailing zeros.
*/
if (strip)
if (set.form != com.ibm.icu.math.MathContext.PLAIN) {
d = this.mant.length;
/* see if we need to drop any trailing zeros */
{
i = d - 1;
i: for (; i >= 1; i--) {
if (this.mant[i] != 0)
break i;
d--;
exp++;
}
}/* i */
if (d < this.mant.length) {/* need to reduce */
newmant = new byte[d];
java.lang.System.arraycopy(this.mant, 0, newmant, 0, d);
this.mant = newmant;
}
}
form = (byte) com.ibm.icu.math.MathContext.PLAIN; // preset
/* Now check for leading- and all- zeros in mantissa */
{
int $26 = this.mant.length;
i = 0;
for (; $26 > 0; $26--, i++) {
if (this.mant[i] != 0) {
// non-0 result; ind will be correct
// remove leading zeros [e.g., after subtract]
if (i > 0) {
do {
newmant = new byte[this.mant.length - i];
java.lang.System.arraycopy(this.mant, i, newmant, 0,
this.mant.length - i);
this.mant = newmant;
} while (false);
}/* delead */
// now determine form if not PLAIN
mag = exp + mant.length;
if (mag > 0) { // most common path
if (mag > set.digits)
if (set.digits != 0)
form = (byte) set.form;
if ((mag - 1) <= MaxExp)
return this; // no overflow; quick return
} else if (mag < (-5))
form = (byte) set.form;
/* check for overflow */
mag--;
if ((mag < MinExp) | (mag > MaxExp)) {
overflow: do {
// possible reprieve if form is engineering
if (form == com.ibm.icu.math.MathContext.ENGINEERING) {
sig = mag % 3; // leftover
if (sig < 0)
sig = 3 + sig; // negative exponent
mag = mag - sig; // exponent to use
// 1999.06.29: second test here must be MaxExp
if (mag >= MinExp)
if (mag <= MaxExp)
break overflow;
}
throw new java.lang.ArithmeticException("Exponent Overflow:" + " " + mag);
} while (false);
}/* overflow */
return this;
}
}
}/* i */
// Drop through to here only if mantissa is all zeros
ind = iszero;
{/* select */
if (set.form != com.ibm.icu.math.MathContext.PLAIN)
exp = 0; // standard result; go to '0'
else if (exp > 0)
exp = 0; // +ve exponent also goes to '0'
else {
// a plain number with -ve exponent; preserve and check exponent
if (exp < MinExp)
throw new java.lang.ArithmeticException("Exponent Overflow:" + " " + exp);
}
}
mant = ZERO.mant; // canonical mantissa
return this;
}
}