| //##header J2SE15 |
| /* 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.impl.Utility; |
| |
| /* ------------------------------------------------------------------ */ |
| /* BigDecimal -- Decimal arithmetic for Java */ |
| /* ------------------------------------------------------------------ */ |
| /* Copyright IBM Corporation, 1996-2008. 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) <sigh>; 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 <code>BigDecimal</code> class implements immutable |
| * arbitrary-precision decimal numbers. The methods of the |
| * <code>BigDecimal</code> class provide operations for fixed and |
| * floating point arithmetic, comparison, format conversions, and |
| * hashing. |
| * <p> |
| * As the numbers are decimal, there is an exact correspondence between |
| * an instance of a <code>BigDecimal</code> object and its |
| * <code>String</code> representation; the <code>BigDecimal</code> class |
| * provides direct conversions to and from <code>String</code> and |
| * character array (<code>char[]</code>) objects, as well as conversions |
| * to and from the Java primitive types (which may not be exact) and |
| * <code>BigInteger</code>. |
| * <p> |
| * In the descriptions of constructors and methods in this documentation, |
| * the value of a <code>BigDecimal</code> number object is shown as the |
| * result of invoking the <code>toString()</code> 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. |
| * <p> |
| * The floating point arithmetic provided by this class is defined by |
| * the ANSI X3.274-1996 standard, and is also documented at |
| * <code>http://www2.hursley.ibm.com/decimal</code> |
| * <br><i>[This URL will change.]</i> |
| * |
| * <h3>Operator methods</h3> |
| * <p> |
| * Operations on <code>BigDecimal</code> numbers are controlled by a |
| * {@link MathContext} object, which provides the context (precision and |
| * other information) for the operation. Methods that can take a |
| * <code>MathContext</code> parameter implement the standard arithmetic |
| * operators for <code>BigDecimal</code> objects and are known as |
| * <i>operator methods</i>. The default settings provided by the |
| * constant {@link MathContext#DEFAULT} (<code>digits=9, |
| * form=SCIENTIFIC, lostDigits=false, roundingMode=ROUND_HALF_UP</code>) |
| * perform general-purpose floating point arithmetic to nine digits of |
| * precision. The <code>MathContext</code> parameter must not be |
| * <code>null</code>. |
| * <p> |
| * Each operator method also has a version provided which does |
| * not take a <code>MathContext</code> parameter. For this version of |
| * each method, the context settings used are <code>digits=0, |
| * form=PLAIN, lostDigits=false, roundingMode=ROUND_HALF_UP</code>; |
| * these settings perform fixed point arithmetic with unlimited |
| * precision, as defined for the original BigDecimal class in Java 1.1 |
| * and Java 1.2. |
| * <p> |
| * For monadic operators, only the optional <code>MathContext</code> |
| * parameter is present; the operation acts upon the current object. |
| * <p> |
| * For dyadic operators, a <code>BigDecimal</code> parameter is always |
| * present; it must not be <code>null</code>. |
| * The operation acts with the current object being the left-hand operand |
| * and the <code>BigDecimal</code> parameter being the right-hand operand. |
| * <p> |
| * For example, adding two <code>BigDecimal</code> objects referred to |
| * by the names <code>award</code> and <code>extra</code> could be |
| * written as any of: |
| * <p><code> |
| * award.add(extra) |
| * <br>award.add(extra, MathContext.DEFAULT) |
| * <br>award.add(extra, acontext) |
| * </code> |
| * <p> |
| * (where <code>acontext</code> is a <code>MathContext</code> object), |
| * which would return a <code>BigDecimal</code> object whose value is |
| * the result of adding <code>award</code> and <code>extra</code> under |
| * the appropriate context settings. |
| * <p> |
| * When a <code>BigDecimal</code> 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: |
| * <ul> |
| * <li>Results are normally calculated with up to some maximum number of |
| * significant digits. |
| * For example, if the <code>MathContext</code> parameter for an operation |
| * were <code>MathContext.DEFAULT</code> then the result would be |
| * rounded to 9 digits; the division of 2 by 3 would then result in |
| * 0.666666667. |
| * <br> |
| * You can change the default of 9 significant digits by providing the |
| * method with a suitable <code>MathContext</code> object. This lets you |
| * calculate using as many digits as you need -- thousands, if necessary. |
| * Fixed point (scaled) arithmetic is indicated by using a |
| * <code>digits</code> setting of 0 (or omitting the |
| * <code>MathContext</code> parameter). |
| * <br> |
| * Similarly, you can change the algorithm used for rounding from the |
| * default "classic" algorithm. |
| * <li> |
| * In standard arithmetic (that is, when the <code>form</code> setting |
| * is not <code>PLAIN</code>), a zero result is always expressed as the |
| * single digit <code>'0'</code> (that is, with no sign, decimal point, |
| * or exponent part). |
| * <li> |
| * 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). |
| * <br> |
| * So, for example: |
| * <p><code> |
| * new BigDecimal("2.40").add( new BigDecimal("2")) => "4.40" |
| * <br>new BigDecimal("2.40").subtract(new BigDecimal("2")) => "0.40" |
| * <br>new BigDecimal("2.40").multiply(new BigDecimal("2")) => "4.80" |
| * <br>new BigDecimal("2.40").divide( new BigDecimal("2"), def) => "1.2" |
| * </code> |
| * <p>where the value on the right of the <code>=></code> would be the |
| * result of the operation, expressed as a <code>String</code>, and |
| * <code>def</code> (in this and following examples) refers to |
| * <code>MathContext.DEFAULT</code>). |
| * 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. |
| * <li> |
| * In standard arithmetic, exponential form is used for a result |
| * depending on its value and the current setting of <code>digits</code> |
| * (the default is 9 digits). |
| * If the number of places needed before the decimal point exceeds the |
| * <code>digits</code> setting, or the absolute value of the number is |
| * less than <code>0.000001</code>, then the number will be expressed in |
| * exponential notation; thus |
| * <p><code> |
| * new BigDecimal("1e+6").multiply(new BigDecimal("1e+6"), def) |
| * </code> |
| * <p>results in <code>1E+12</code> instead of |
| * <code>1000000000000</code>, and |
| * <p><code> |
| * new BigDecimal("1").divide(new BigDecimal("3E+10"), def) |
| * </code> |
| * <p>results in <code>3.33333333E-11</code> instead of |
| * <code>0.0000000000333333333</code>. |
| * <p> |
| * The form of the exponential notation (scientific or engineering) is |
| * determined by the <code>form</code> setting. |
| * <eul> |
| * <p> |
| * The names of methods in this class follow the conventions established |
| * by <code>java.lang.Number</code>, <code>java.math.BigInteger</code>, |
| * and <code>java.math.BigDecimal</code> 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 <code>BigDecimal</code> 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 <code>BigDecimal</code> 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 <code>BigDecimal</code> 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: |
| * <ul> |
| * <li>ispos -- the number is positive |
| * <li>iszero -- the number is zero |
| * <li>isneg -- the number is negative |
| * </ul> |
| * |
| * @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: |
| * <ul> |
| * <li>MathContext.PLAIN -- no exponent needed |
| * <li>MathContext.SCIENTIFIC -- scientific notation required |
| * <li>MathContext.ENGINEERING -- engineering notation required |
| * </ul> |
| * <p> |
| * 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. |
| * <p> |
| * Once constructed, this may become shared between several BigDecimal |
| * objects, so must not be altered. |
| * <p> |
| * For efficiency (speed), this is a byte array, with each byte |
| * taking a value of 0 -> 9. |
| * <p> |
| * 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. |
| * <p> |
| * For fixed point arithmetic, scale is <code>-exp</code>, 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 */ |
| /* ---------------------------------------------------------------- */ |
| |
| //#if defined(FOUNDATION10) |
| //#else |
| /** |
| * Constructs a <code>BigDecimal</code> object from a |
| * <code>java.math.BigDecimal</code>. |
| * <p> |
| * Constructs a <code>BigDecimal</code> as though the parameter had |
| * been represented as a <code>String</code> (using its |
| * <code>toString</code> method) and the |
| * {@link #BigDecimal(java.lang.String)} constructor had then been |
| * used. |
| * The parameter must not be <code>null</code>. |
| * <p> |
| * <i>(Note: this constructor is provided only in the |
| * <code>com.ibm.icu.math</code> version of the BigDecimal class. |
| * It would not be present in a <code>java.math</code> version.)</i> |
| * |
| * @param bd The <code>BigDecimal</code> to be translated. |
| * @stable ICU 2.0 |
| */ |
| |
| public BigDecimal(java.math.BigDecimal bd){ |
| this(bd.toString()); |
| return;} |
| //#endif |
| |
| /** |
| * Constructs a <code>BigDecimal</code> object from a |
| * <code>BigInteger</code>, with scale 0. |
| * <p> |
| * Constructs a <code>BigDecimal</code> which is the exact decimal |
| * representation of the <code>BigInteger</code>, with a scale of |
| * zero. |
| * The value of the <code>BigDecimal</code> is identical to the value |
| * of the <code>BigInteger</code>. |
| * The parameter must not be <code>null</code>. |
| * <p> |
| * The <code>BigDecimal</code> will contain only decimal digits, |
| * prefixed with a leading minus sign (hyphen) if the |
| * <code>BigInteger</code> is negative. A leading zero will be |
| * present only if the <code>BigInteger</code> is zero. |
| * |
| * @param bi The <code>BigInteger</code> to be converted. |
| * @stable ICU 2.0 |
| */ |
| |
| public BigDecimal(java.math.BigInteger bi){ |
| this(bi.toString(10)); |
| return;} |
| // exp remains 0 |
| |
| /** |
| * Constructs a <code>BigDecimal</code> object from a |
| * <code>BigInteger</code> and a scale. |
| * <p> |
| * Constructs a <code>BigDecimal</code> which is the exact decimal |
| * representation of the <code>BigInteger</code>, scaled by the |
| * second parameter, which may not be negative. |
| * The value of the <code>BigDecimal</code> is the |
| * <code>BigInteger</code> divided by ten to the power of the scale. |
| * The <code>BigInteger</code> parameter must not be |
| * <code>null</code>. |
| * <p> |
| * The <code>BigDecimal</code> will contain only decimal digits, (with |
| * an embedded decimal point followed by <code>scale</code> decimal |
| * digits if the scale is positive), prefixed with a leading minus |
| * sign (hyphen) if the <code>BigInteger</code> is negative. A |
| * leading zero will be present only if the <code>BigInteger</code> is |
| * zero. |
| * |
| * @param bi The <code>BigInteger</code> to be converted. |
| * @param scale The <code>int</code> 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=(int)-scale; // exponent is -scale |
| return;} |
| |
| /** |
| * Constructs a <code>BigDecimal</code> object from an array of characters. |
| * <p> |
| * Constructs a <code>BigDecimal</code> as though a |
| * <code>String</code> had been constructed from the character array |
| * and the {@link #BigDecimal(java.lang.String)} constructor had then |
| * been used. The parameter must not be <code>null</code>. |
| * <p> |
| * Using this constructor is faster than using the |
| * <code>BigDecimal(String)</code> constructor if the string is |
| * already available in character array form. |
| * |
| * @param inchars The <code>char[]</code> 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 <code>BigDecimal</code> object from an array of characters. |
| * <p> |
| * Constructs a <code>BigDecimal</code> as though a |
| * <code>String</code> 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 <code>null</code>, and the |
| * subarray must be wholly contained within it. |
| * <p> |
| * Using this constructor is faster than using the |
| * <code>BigDecimal(String)</code> constructor if the string is |
| * already available within a character array. |
| * |
| * @param inchars The <code>char[]</code> array containing the number |
| * to be converted. |
| * @param offset The <code>int</code> offset into the array of the |
| * start of the number to be converted. |
| * @param length The <code>int</code> 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 ((!(java.lang.Character.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 ((!(java.lang.Character.isDigit(sj)))) |
| bad(inchars); // not a number |
| dvalue=java.lang.Character.digit(sj,10); // check base |
| if (dvalue<0) |
| bad(inchars); // not base 10 |
| } |
| else |
| dvalue=((int)(sj))-((int)('0')); |
| exp=(exp*10)+dvalue; |
| } |
| }/*j*/ |
| if (eneg) |
| exp=(int)-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 ((java.lang.Character.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)(((int)(sj))-((int)('0')));/* easy */ |
| else |
| { |
| dvalue=java.lang.Character.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)(((int)(inchars[j]))-((int)('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 <code>BigDecimal</code> object directly from a |
| * <code>double</code>. |
| * <p> |
| * Constructs a <code>BigDecimal</code> which is the exact decimal |
| * representation of the 64-bit signed binary floating point |
| * parameter. |
| * <p> |
| * Note that this constructor it an exact conversion; it does not give |
| * the same result as converting <code>num</code> to a |
| * <code>String</code> using the <code>Double.toString()</code> 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 <code>BigDecimal</code> from a |
| * <code>double</code>. |
| * |
| * @param num The <code>double</code> 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 |
| //#if defined(FOUNDATION10) |
| //## this(String.valueOf(num)); |
| //#else |
| this((new java.math.BigDecimal(num)).toString()); |
| //#endif |
| return;} |
| /** |
| * Constructs a <code>BigDecimal</code> object directly from a |
| * <code>int</code>. |
| * <p> |
| * Constructs a <code>BigDecimal</code> which is the exact decimal |
| * representation of the 32-bit signed binary integer parameter. |
| * The <code>BigDecimal</code> 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 <code>int</code> 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)((int)-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=(int)-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 <code>BigDecimal</code> object directly from a |
| * <code>long</code>. |
| * <p> |
| * Constructs a <code>BigDecimal</code> which is the exact decimal |
| * representation of the 64-bit signed binary integer parameter. |
| * The <code>BigDecimal</code> 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 <code>long</code> 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=(long)-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 <code>BigDecimal</code> object from a <code>String</code>. |
| * <p> |
| * Constructs a <code>BigDecimal</code> from the parameter, which must |
| * not be <code>null</code> and must represent a valid <i>number</i>, |
| * as described formally in the documentation referred to |
| * {@link BigDecimal above}. |
| * <p> |
| * In summary, numbers in <code>String</code> 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. |
| * <p> |
| * Some valid strings from which a <code>BigDecimal</code> might |
| * be constructed are: |
| * <pre> |
| * "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 |
| * </pre> |
| * <p> |
| * (Exponential notation means that the number includes an optional |
| * sign and a power of ten following an '</code>E</code>' that |
| * indicates how the decimal point will be shifted. Thus the |
| * <code>"4E+9"</code> above is just a short way of writing |
| * <code>4000000000</code>, and the <code>"0.73e-7"</code> is short |
| * for <code>0.000000073</code>.) |
| * <p> |
| * The <code>BigDecimal</code> 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 |
| * <code>e</code> or an <code>E</code>), then the |
| * <code>BigDecimal</code> 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. |
| * <p> |
| * Any digits in the parameter must be decimal; that is, |
| * <code>Character.digit(c, 10)</code> (where </code>c</code> is the |
| * character in question) would not return -1. |
| * |
| * @param string The <code>String</code> 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;} |
| |
| /* <sgml> Make a default BigDecimal object for local use. </sgml> */ |
| |
| private BigDecimal(){super(); |
| return; |
| } |
| |
| /* ---------------------------------------------------------------- */ |
| /* Operator methods [methods which take a context parameter] */ |
| /* ---------------------------------------------------------------- */ |
| |
| /** |
| * Returns a plain <code>BigDecimal</code> whose value is the absolute |
| * value of this <code>BigDecimal</code>. |
| * <p> |
| * The same as {@link #abs(MathContext)}, where the context is |
| * <code>new MathContext(0, MathContext.PLAIN)</code>. |
| * <p> |
| * The length of the decimal part (the scale) of the result will |
| * be <code>this.scale()</code> |
| * |
| * @return A <code>BigDecimal</code> whose value is the absolute |
| * value of this <code>BigDecimal</code>. |
| * @stable ICU 2.0 |
| */ |
| |
| public com.ibm.icu.math.BigDecimal abs(){ |
| return this.abs(plainMC); |
| } |
| |
| /** |
| * Returns a <code>BigDecimal</code> whose value is the absolute value |
| * of this <code>BigDecimal</code>. |
| * <p> |
| * 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 <code>MathContext</code> arithmetic settings. |
| * @return A <code>BigDecimal</code> whose value is the absolute |
| * value of this <code>BigDecimal</code>. |
| * @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 <code>BigDecimal</code> whose value is |
| * <code>this+rhs</code>, using fixed point arithmetic. |
| * <p> |
| * The same as {@link #add(BigDecimal, MathContext)}, |
| * where the <code>BigDecimal</code> is <code>rhs</code>, |
| * and the context is <code>new MathContext(0, MathContext.PLAIN)</code>. |
| * <p> |
| * 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 <code>BigDecimal</code> for the right hand side of |
| * the addition. |
| * @return A <code>BigDecimal</code> whose value is |
| * <code>this+rhs</code>, 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 <code>BigDecimal</code> whose value is <code>this+rhs</code>. |
| * <p> |
| * Implements the addition (<b><code>+</code></b>) operator |
| * (as defined in the decimal documentation, see {@link BigDecimal |
| * class header}), |
| * and returns the result as a <code>BigDecimal</code> object. |
| * |
| * @param rhs The <code>BigDecimal</code> for the right hand side of |
| * the addition. |
| * @param set The <code>MathContext</code> arithmetic settings. |
| * @return A <code>BigDecimal</code> whose value is |
| * <code>this+rhs</code>. |
| * @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 <code>BigDecimal</code> to another, using unlimited |
| * precision. |
| * <p> |
| * The same as {@link #compareTo(BigDecimal, MathContext)}, |
| * where the <code>BigDecimal</code> is <code>rhs</code>, |
| * and the context is <code>new MathContext(0, MathContext.PLAIN)</code>. |
| * |
| * @param rhs The <code>BigDecimal</code> for the right hand side of |
| * the comparison. |
| * @return An <code>int</code> whose value is -1, 0, or 1 as |
| * <code>this</code> is numerically less than, equal to, |
| * or greater than <code>rhs</code>. |
| * @see #compareTo(Object) |
| * @stable ICU 2.0 |
| */ |
| |
| public int compareTo(com.ibm.icu.math.BigDecimal rhs){ |
| return this.compareTo(rhs,plainMC); |
| } |
| |
| /** |
| * Compares this <code>BigDecimal</code> to another. |
| * <p> |
| * Implements numeric comparison, |
| * (as defined in the decimal documentation, see {@link BigDecimal |
| * class header}), |
| * and returns a result of type <code>int</code>. |
| * <p> |
| * The result will be: |
| * <table cellpadding=2><tr> |
| * <td align=right><b>-1</b></td> |
| * <td>if the current object is less than the first parameter</td> |
| * </tr><tr> |
| * <td align=right><b>0</b></td> |
| * <td>if the current object is equal to the first parameter</td> |
| * </tr><tr> |
| * <td align=right><b>1</b></td> |
| * <td>if the current object is greater than the first parameter.</td> |
| * </tr></table> |
| * <p> |
| * A {@link #compareTo(Object)} method is also provided. |
| * |
| * @param rhs The <code>BigDecimal</code> for the right hand side of |
| * the comparison. |
| * @param set The <code>MathContext</code> arithmetic settings. |
| * @return An <code>int</code> whose value is -1, 0, or 1 as |
| * <code>this</code> is numerically less than, equal to, |
| * or greater than <code>rhs</code>. |
| * @see #compareTo(Object) |
| * @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 <code>BigDecimal</code> whose value is |
| * <code>this/rhs</code>, using fixed point arithmetic. |
| * <p> |
| * The same as {@link #divide(BigDecimal, int)}, |
| * where the <code>BigDecimal</code> is <code>rhs</code>, |
| * 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 <code>BigDecimal</code> for the right hand side of |
| * the division. |
| * @return A plain <code>BigDecimal</code> whose value is |
| * <code>this/rhs</code>, using fixed point arithmetic. |
| * @throws ArithmeticException if <code>rhs</code> 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 <code>BigDecimal</code> whose value is |
| * <code>this/rhs</code>, using fixed point arithmetic and a |
| * rounding mode. |
| * <p> |
| * The same as {@link #divide(BigDecimal, int, int)}, |
| * where the <code>BigDecimal</code> is <code>rhs</code>, |
| * and the second parameter is <code>this.scale()</code>, and |
| * the third is <code>round</code>. |
| * <p> |
| * 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. |
| * <p> |
| * @param rhs The <code>BigDecimal</code> for the right hand side of |
| * the division. |
| * @param round The <code>int</code> rounding mode to be used for |
| * the division (see the {@link MathContext} class). |
| * @return A plain <code>BigDecimal</code> whose value is |
| * <code>this/rhs</code>, using fixed point arithmetic |
| * and the specified rounding mode. |
| * @throws IllegalArgumentException if <code>round</code> is not a |
| * valid rounding mode. |
| * @throws ArithmeticException if <code>rhs</code> is zero. |
| * @throws ArithmeticException if <code>round</code> is {@link |
| * MathContext#ROUND_UNNECESSARY} and |
| * <code>this.scale()</code> 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 <code>BigDecimal</code> whose value is |
| * <code>this/rhs</code>, using fixed point arithmetic and a |
| * given scale and rounding mode. |
| * <p> |
| * The same as {@link #divide(BigDecimal, MathContext)}, |
| * where the <code>BigDecimal</code> is <code>rhs</code>, |
| * <code>new MathContext(0, MathContext.PLAIN, false, round)</code>, |
| * except that the length of the decimal part (the scale) to be used |
| * for the result is explicit rather than being taken from |
| * <code>this</code>. |
| * <p> |
| * 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. |
| * <p> |
| * @param rhs The <code>BigDecimal</code> for the right hand side of |
| * the division. |
| * @param scale The <code>int</code> scale to be used for the result. |
| * @param round The <code>int</code> rounding mode to be used for |
| * the division (see the {@link MathContext} class). |
| * @return A plain <code>BigDecimal</code> whose value is |
| * <code>this/rhs</code>, using fixed point arithmetic |
| * and the specified rounding mode. |
| * @throws IllegalArgumentException if <code>round</code> is not a |
| * valid rounding mode. |
| * @throws ArithmeticException if <code>rhs</code> is zero. |
| * @throws ArithmeticException if <code>scale</code> is negative. |
| * @throws ArithmeticException if <code>round</code> is {@link |
| * MathContext#ROUND_UNNECESSARY} and <code>scale</code> |
| * 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 <code>BigDecimal</code> whose value is <code>this/rhs</code>. |
| * <p> |
| * Implements the division (<b><code>/</code></b>) operator |
| * (as defined in the decimal documentation, see {@link BigDecimal |
| * class header}), |
| * and returns the result as a <code>BigDecimal</code> object. |
| * |
| * @param rhs The <code>BigDecimal</code> for the right hand side of |
| * the division. |
| * @param set The <code>MathContext</code> arithmetic settings. |
| * @return A <code>BigDecimal</code> whose value is |
| * <code>this/rhs</code>. |
| * @throws ArithmeticException if <code>rhs</code> 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 <code>BigDecimal</code> whose value is the integer |
| * part of <code>this/rhs</code>. |
| * <p> |
| * The same as {@link #divideInteger(BigDecimal, MathContext)}, |
| * where the <code>BigDecimal</code> is <code>rhs</code>, |
| * and the context is <code>new MathContext(0, MathContext.PLAIN)</code>. |
| * |
| * @param rhs The <code>BigDecimal</code> for the right hand side of |
| * the integer division. |
| * @return A <code>BigDecimal</code> whose value is the integer |
| * part of <code>this/rhs</code>. |
| * @throws ArithmeticException if <code>rhs</code> 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 <code>BigDecimal</code> whose value is the integer |
| * part of <code>this/rhs</code>. |
| * <p> |
| * Implements the integer division operator |
| * (as defined in the decimal documentation, see {@link BigDecimal |
| * class header}), |
| * and returns the result as a <code>BigDecimal</code> object. |
| * |
| * @param rhs The <code>BigDecimal</code> for the right hand side of |
| * the integer division. |
| * @param set The <code>MathContext</code> arithmetic settings. |
| * @return A <code>BigDecimal</code> whose value is the integer |
| * part of <code>this/rhs</code>. |
| * @throws ArithmeticException if <code>rhs</code> 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 <code>BigDecimal</code> whose value is |
| * the maximum of <code>this</code> and <code>rhs</code>. |
| * <p> |
| * The same as {@link #max(BigDecimal, MathContext)}, |
| * where the <code>BigDecimal</code> is <code>rhs</code>, |
| * and the context is <code>new MathContext(0, MathContext.PLAIN)</code>. |
| * |
| * @param rhs The <code>BigDecimal</code> for the right hand side of |
| * the comparison. |
| * @return A <code>BigDecimal</code> whose value is |
| * the maximum of <code>this</code> and <code>rhs</code>. |
| * @stable ICU 2.0 |
| */ |
| |
| public com.ibm.icu.math.BigDecimal max(com.ibm.icu.math.BigDecimal rhs){ |
| return this.max(rhs,plainMC); |
| } |
| |
| /** |
| * Returns a <code>BigDecimal</code> whose value is |
| * the maximum of <code>this</code> and <code>rhs</code>. |
| * <p> |
| * Returns the larger of the current object and the first parameter. |
| * <p> |
| * If calling the {@link #compareTo(BigDecimal, MathContext)} method |
| * with the same parameters would return <code>1</code> or |
| * <code>0</code>, then the result of calling the |
| * {@link #plus(MathContext)} method on the current object (using the |
| * same <code>MathContext</code> parameter) is returned. |
| * Otherwise, the result of calling the {@link #plus(MathContext)} |
| * method on the first parameter object (using the same |
| * <code>MathContext</code> parameter) is returned. |
| * |
| * @param rhs The <code>BigDecimal</code> for the right hand side of |
| * the comparison. |
| * @param set The <code>MathContext</code> arithmetic settings. |
| * @return A <code>BigDecimal</code> whose value is |
| * the maximum of <code>this</code> and <code>rhs</code>. |
| * @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 <code>BigDecimal</code> whose value is |
| * the minimum of <code>this</code> and <code>rhs</code>. |
| * <p> |
| * The same as {@link #min(BigDecimal, MathContext)}, |
| * where the <code>BigDecimal</code> is <code>rhs</code>, |
| * and the context is <code>new MathContext(0, MathContext.PLAIN)</code>. |
| * |
| * @param rhs The <code>BigDecimal</code> for the right hand side of |
| * the comparison. |
| * @return A <code>BigDecimal</code> whose value is |
| * the minimum of <code>this</code> and <code>rhs</code>. |
| * @stable ICU 2.0 |
| */ |
| |
| public com.ibm.icu.math.BigDecimal min(com.ibm.icu.math.BigDecimal rhs){ |
| return this.min(rhs,plainMC); |
| } |
| |
| /** |
| * Returns a <code>BigDecimal</code> whose value is |
| * the minimum of <code>this</code> and <code>rhs</code>. |
| * <p> |
| * Returns the smaller of the current object and the first parameter. |
| * <p> |
| * If calling the {@link #compareTo(BigDecimal, MathContext)} method |
| * with the same parameters would return <code>-1</code> or |
| * <code>0</code>, then the result of calling the |
| * {@link #plus(MathContext)} method on the current object (using the |
| * same <code>MathContext</code> parameter) is returned. |
| * Otherwise, the result of calling the {@link #plus(MathContext)} |
| * method on the first parameter object (using the same |
| * <code>MathContext</code> parameter) is returned. |
| * |
| * @param rhs The <code>BigDecimal</code> for the right hand side of |
| * the comparison. |
| * @param set The <code>MathContext</code> arithmetic settings. |
| * @return A <code>BigDecimal</code> whose value is |
| * the minimum of <code>this</code> and <code>rhs</code>. |
| * @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 <code>BigDecimal</code> whose value is |
| * <code>this*rhs</code>, using fixed point arithmetic. |
| * <p> |
| * The same as {@link #add(BigDecimal, MathContext)}, |
| * where the <code>BigDecimal</code> is <code>rhs</code>, |
| * and the context is <code>new MathContext(0, MathContext.PLAIN)</code>. |
| * <p> |
| * 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 <code>BigDecimal</code> for the right hand side of |
| * the multiplication. |
| * @return A <code>BigDecimal</code> whose value is |
| * <code>this*rhs</code>, 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 <code>BigDecimal</code> whose value is <code>this*rhs</code>. |
| * <p> |
| * Implements the multiplication (<b><code>*</code></b>) operator |
| * (as defined in the decimal documentation, see {@link BigDecimal |
| * class header}), |
| * and returns the result as a <code>BigDecimal</code> object. |
| * |
| * @param rhs The <code>BigDecimal</code> for the right hand side of |
| * the multiplication. |
| * @param set The <code>MathContext</code> arithmetic settings. |
| * @return A <code>BigDecimal</code> whose value is |
| * <code>this*rhs</code>. |
| * @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 <code>BigDecimal</code> whose value is |
| * <code>-this</code>. |
| * <p> |
| * The same as {@link #negate(MathContext)}, where the context is |
| * <code>new MathContext(0, MathContext.PLAIN)</code>. |
| * <p> |
| * The length of the decimal part (the scale) of the result will be |
| * be <code>this.scale()</code> |
| * |
| * |
| * @return A <code>BigDecimal</code> whose value is |
| * <code>-this</code>. |
| * @stable ICU 2.0 |
| */ |
| |
| public com.ibm.icu.math.BigDecimal negate(){ |
| return this.negate(plainMC); |
| } |
| |
| /** |
| * Returns a <code>BigDecimal</code> whose value is <code>-this</code>. |
| * <p> |
| * Implements the negation (Prefix <b><code>-</code></b>) operator |
| * (as defined in the decimal documentation, see {@link BigDecimal |
| * class header}), |
| * and returns the result as a <code>BigDecimal</code> object. |
| * |
| * @param set The <code>MathContext</code> arithmetic settings. |
| * @return A <code>BigDecimal</code> whose value is |
| * <code>-this</code>. |
| * @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 <code>BigDecimal</code> whose value is |
| * <code>+this</code>. |
| * Note that <code>this</code> is not necessarily a |
| * plain <code>BigDecimal</code>, but the result will always be. |
| * <p> |
| * The same as {@link #plus(MathContext)}, where the context is |
| * <code>new MathContext(0, MathContext.PLAIN)</code>. |
| * <p> |
| * The length of the decimal part (the scale) of the result will be |
| * be <code>this.scale()</code> |
| * |
| * @return A <code>BigDecimal</code> whose value is |
| * <code>+this</code>. |
| * @stable ICU 2.0 |
| */ |
| |
| public com.ibm.icu.math.BigDecimal plus(){ |
| return this.plus(plainMC); |
| } |
| |
| /** |
| * Returns a <code>BigDecimal</code> whose value is |
| * <code>+this</code>. |
| * <p> |
| * Implements the plus (Prefix <b><code>+</code></b>) operator |
| * (as defined in the decimal documentation, see {@link BigDecimal |
| * class header}), |
| * and returns the result as a <code>BigDecimal</code> object. |
| * <p> |
| * This method is useful for rounding or otherwise applying a context |
| * to a decimal value. |
| * |
| * @param set The <code>MathContext</code> arithmetic settings. |
| * @return A <code>BigDecimal</code> whose value is |
| * <code>+this</code>. |
| * @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 <code>BigDecimal</code> whose value is |
| * <code>this**rhs</code>, using fixed point arithmetic. |
| * <p> |
| * The same as {@link #pow(BigDecimal, MathContext)}, |
| * where the <code>BigDecimal</code> is <code>rhs</code>, |
| * and the context is <code>new MathContext(0, MathContext.PLAIN)</code>. |
| * <p> |
| * The parameter is the power to which the <code>this</code> 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. |
| * <p> |
| * In addition, the power must not be negative, as no |
| * <code>MathContext</code> is used and so the result would then |
| * always be 0. |
| * |
| * @param rhs The <code>BigDecimal</code> for the right hand side of |
| * the operation (the power). |
| * @return A <code>BigDecimal</code> whose value is |
| * <code>this**rhs</code>, using fixed point arithmetic. |
| * @throws ArithmeticException if <code>rhs</code> 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 <code>BigDecimal</code> whose value is <code>this**rhs</code>. |
| * <p> |
| * Implements the power (<b><code>**</code></b>) operator |
| * (as defined in the decimal documentation, see {@link BigDecimal |
| * class header}), |
| * and returns the result as a <code>BigDecimal</code> object. |
| * <p> |
| * The first parameter is the power to which the <code>this</code> |
| * 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. |
| * <p> |
| * If the <code>digits</code> setting of the <code>MathContext</code> |
| * parameter is 0, the power must be zero or positive. |
| * |
| * @param rhs The <code>BigDecimal</code> for the right hand side of |
| * the operation (the power). |
| * @param set The <code>MathContext</code> arithmetic settings. |
| * @return A <code>BigDecimal</code> whose value is |
| * <code>this**rhs</code>. |
| * @throws ArithmeticException if <code>rhs</code> 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=(int)-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 <code>BigDecimal</code> whose value is |
| * the remainder of <code>this/rhs</code>, using fixed point arithmetic. |
| * <p> |
| * The same as {@link #remainder(BigDecimal, MathContext)}, |
| * where the <code>BigDecimal</code> is <code>rhs</code>, |
| * and the context is <code>new MathContext(0, MathContext.PLAIN)</code>. |
| * <p> |
| * This is not the modulo operator -- the result may be negative. |
| * |
| * @param rhs The <code>BigDecimal</code> for the right hand side of |
| * the remainder operation. |
| * @return A <code>BigDecimal</code> whose value is the remainder |
| * of <code>this/rhs</code>, using fixed point arithmetic. |
| * @throws ArithmeticException if <code>rhs</code> 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 <code>BigDecimal</code> whose value is the remainder of |
| * <code>this/rhs</code>. |
| * <p> |
| * Implements the remainder operator |
| * (as defined in the decimal documentation, see {@link BigDecimal |
| * class header}), |
| * and returns the result as a <code>BigDecimal</code> object. |
| * <p> |
| * This is not the modulo operator -- the result may be negative. |
| * |
| * @param rhs The <code>BigDecimal</code> for the right hand side of |
| * the remainder operation. |
| * @param set The <code>MathContext</code> arithmetic settings. |
| * @return A <code>BigDecimal</code> whose value is the remainder |
| * of <code>this+rhs</code>. |
| * @throws ArithmeticException if <code>rhs</code> 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 <code>BigDecimal</code> whose value is |
| * <code>this-rhs</code>, using fixed point arithmetic. |
| * <p> |
| * The same as {@link #subtract(BigDecimal, MathContext)}, |
| * where the <code>BigDecimal</code> is <code>rhs</code>, |
| * and the context is <code>new MathContext(0, MathContext.PLAIN)</code>. |
| * <p> |
| * 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 <code>BigDecimal</code> for the right hand side of |
| * the subtraction. |
| * @return A <code>BigDecimal</code> whose value is |
| * <code>this-rhs</code>, 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 <code>BigDecimal</code> whose value is <code>this-rhs</code>. |
| * <p> |
| * Implements the subtraction (<b><code>-</code></b>) operator |
| * (as defined in the decimal documentation, see {@link BigDecimal |
| * class header}), |
| * and returns the result as a <code>BigDecimal</code> object. |
| * |
| * @param rhs The <code>BigDecimal</code> for the right hand side of |
| * the subtraction. |
| * @param set The <code>MathContext</code> arithmetic settings. |
| * @return A <code>BigDecimal</code> whose value is |
| * <code>this-rhs</code>. |
| * @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 <code>BigDecimal</code> to a <code>byte</code>. |
| * If the <code>BigDecimal</code> has a non-zero decimal part or is |
| * out of the possible range for a <code>byte</code> (8-bit signed |
| * integer) result then an <code>ArithmeticException</code> is thrown. |
| * |
| * @return A <code>byte</code> equal in value to <code>this</code>. |
| * @throws ArithmeticException if <code>this</code> has a non-zero |
| * decimal part, or will not fit in a <code>byte</code>. |
| * @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; |
| } |
| |
| /** |
| * Compares this <code>BigDecimal</code> with the value of the parameter. |
| * <p> |
| * If the parameter is <code>null</code>, or is not an instance of the |
| * <code>BigDecimal</code> type, an exception is thrown. |
| * Otherwise, the parameter is cast to type <code>BigDecimal</code> |
| * and the result of the {@link #compareTo(BigDecimal)} method, |
| * using the cast parameter, is returned. |
| * <p> |
| * The {@link #compareTo(BigDecimal, MathContext)} method should be |
| * used when a <code>MathContext</code> is needed for the comparison. |
| * |
| * @param rhsobj The <code>Object</code> for the right hand side of |
| * the comparison. |
| * @return An <code>int</code> whose value is -1, 0, or 1 as |
| * <code>this</code> is numerically less than, equal to, |
| * or greater than <code>rhs</code>. |
| * @throws ClassCastException if <code>rhs</code> cannot be cast to |
| * a <code>BigDecimal</code> object. |
| * @see #compareTo(BigDecimal) |
| * @stable ICU 2.0 |
| */ |
| |
| public int compareTo(java.lang.Object rhsobj){ |
| // the cast in the next line will raise ClassCastException if necessary |
| return compareTo((com.ibm.icu.math.BigDecimal)rhsobj,plainMC); |
| } |
| |
| /** |
| * Converts this <code>BigDecimal</code> to a <code>double</code>. |
| * If the <code>BigDecimal</code> is out of the possible range for a |
| * <code>double</code> (64-bit signed floating point) result then an |
| * <code>ArithmeticException</code> is thrown. |
| * <p> |
| * The double produced is identical to result of expressing the |
| * <code>BigDecimal</code> as a <code>String</code> and then |
| * converting it using the <code>Double(String)</code> constructor; |
| * this can result in values of <code>Double.NEGATIVE_INFINITY</code> |
| * or <code>Double.POSITIVE_INFINITY</code>. |
| * |
| * @return A <code>double</code> corresponding to <code>this</code>. |
| * @stable ICU 2.0 |
| */ |
| |
| 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 <code>BigDecimal</code> with <code>rhs</code> for |
| * equality. |
| * <p> |
| * If the parameter is <code>null</code>, or is not an instance of the |
| * BigDecimal type, or is not exactly equal to the current |
| * <code>BigDecimal</code> object, then <i>false</i> is returned. |
| * Otherwise, <i>true</i> is returned. |
| * <p> |
| * "Exactly equal", here, means that the <code>String</code> |
| * representations of the <code>BigDecimal</code> numbers are |
| * identical (they have the same characters in the same sequence). |
| * <p> |
| * The {@link #compareTo(BigDecimal, MathContext)} method should be |
| * used for more general comparisons. |
| * @param obj The <code>Object</code> for the right hand side of |
| * the comparison. |
| * @return A <code>boolean</code> whose value <i>true</i> if and |
| * only if the operands have identical string representations. |
| * @throws ClassCastException if <code>rhs</code> cannot be cast to |
| * a <code>BigDecimal</code> object. |
| * @stable ICU 2.0 |
| * @see #compareTo(Object) |
| * @see #compareTo(BigDecimal) |
| * @see #compareTo(BigDecimal, MathContext) |
| */ |
| |
| 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 <code>BigDecimal</code> to a <code>float</code>. |
| * If the <code>BigDecimal</code> is out of the possible range for a |
| * <code>float</code> (32-bit signed floating point) result then an |
| * <code>ArithmeticException</code> is thrown. |
| * <p> |
| * The float produced is identical to result of expressing the |
| * <code>BigDecimal</code> as a <code>String</code> and then |
| * converting it using the <code>Float(String)</code> constructor; |
| * this can result in values of <code>Float.NEGATIVE_INFINITY</code> |
| * or <code>Float.POSITIVE_INFINITY</code>. |
| * |
| * @return A <code>float</code> corresponding to <code>this</code>. |
| * @stable ICU 2.0 |
| */ |
| |
| public float floatValue(){ |
| return java.lang.Float.valueOf(this.toString()).floatValue(); |
| } |
| |
| /** |
| * Returns the <code>String</code> representation of this |
| * <code>BigDecimal</code>, modified by layout parameters. |
| * <p> |
| * <i>This method is provided as a primitive for use by more |
| * sophisticated classes, such as <code>DecimalFormat</code>, 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. </i> |
| * <p> |
| * The parameters, for both forms of the <code>format</code> method |
| * are all of type <code>int</code>. |
| * A value of -1 for any parameter indicates that the default action |
| * or value for that parameter should be used. |
| * <p> |
| * The parameters, <code>before</code> and <code>after</code>, |
| * 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. |
| * <p> |
| * <code>before</code> 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 <code>before</code> is |
| * not large enough to contain the integer part of the number |
| * (including the sign, for negative numbers) an exception is thrown. |
| * <p> |
| * <code>after</code> 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 |
| * <code>after</code> 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, |
| * <code>MathContext.ROUND_HALF_UP</code>. |
| * <p> |
| * 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 <code>int</code> specifying the number of places |
| * before the decimal point. Use -1 for 'as many as |
| * are needed'. |
| * @param after The <code>int</code> specifying the number of places |
| * after the decimal point. Use -1 for 'as many as are |
| * needed'. |
| * @return A <code>String</code> representing this |
| * <code>BigDecimal</code>, 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 <code>String</code> representation of this |
| * <code>BigDecimal</code>, modified by layout parameters and allowing |
| * exponential notation. |
| * <p> |
| * <i>This method is provided as a primitive for use by more |
| * sophisticated classes, such as <code>DecimalFormat</code>, 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. </i> |
| * <p> |
| * The parameters are all of type <code>int</code>. |
| * A value of -1 for any parameter indicates that the default action |
| * or value for that parameter should be used. |
| * <p> |
| * The first two parameters (<code>before</code> and |
| * <code>after</code>) 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. |
| * <p> |
| * The remaining parameters control the use of exponential notation |
| * and rounding. Three (<code>explaces</code>, <code>exdigits</code>, |
| * and <code>exform</code>) 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. |
| * <p> |
| * <code>explaces</code> 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 <code>explaces</code> is -1) |
| * being to use as many as are needed. |
| * If <code>explaces</code> is not -1, space is always reserved for |
| * an exponent; if one is not needed (for example, if the exponent |
| * will be 0) then <code>explaces</code>+2 blanks are appended to the |
| * result. |
| * <!-- (This preserves vertical alignment of similarly formatted |
| * numbers in a monospace font.) --> |
| * If <code>explaces</code> is not -1 and is not large enough to |
| * contain the exponent, an exception is thrown. |
| * <p> |
| * <code>exdigits</code> sets the trigger point for use of exponential |
| * notation. If, before any rounding, the number of places needed |
| * before the decimal point exceeds <code>exdigits</code>, or if the |
| * absolute value of the result is less than <code>0.000001</code>, |
| * then exponential form will be used, provided that |
| * <code>exdigits</code> was specified. |
| * When <code>exdigits</code> is -1, exponential notation will never |
| * be used. If 0 is specified for <code>exdigits</code>, exponential |
| * notation is always used unless the exponent would be 0. |
| * <p> |
| * <code>exform</code> 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 (<code>before</code>). Otherwise, only one digit (plus |
| * sign, if negative) is needed. |
| * <p> |
| * Finally, the sixth argument, <code>exround</code>, 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 <code>ROUND_</code>. |
| * The default (<code>ROUND_HALF_UP</code>) may also be selected by |
| * using the value -1, as before. |
| * <p> |
| * The special value <code>MathContext.ROUND_UNNECESSARY</code> may be |
| * used to detect whether non-zero digits are discarded -- if |
| * <code>exround</code> has this value than if non-zero digits would |
| * be discarded (rounded) during formatting then an |
| * <code>ArithmeticException</code> is thrown. |
| * |
| * @param before The <code>int</code> specifying the number of places |
| * before the decimal point. |
| * Use -1 for 'as many as are needed'. |
| * @param after The <code>int</code> specifying the number of places |
| * after the decimal point. |
| * Use -1 for 'as many as are needed'. |
| * @param explaces The <code>int</code> specifying the number of places |
| * to be used for any exponent. |
| * Use -1 for 'as many as are needed'. |
| * @param exdigits The <code>int</code> 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 <code>int</code> specifying the form of |
| * exponential notation to be used |
| * ({@link MathContext#SCIENTIFIC} or |
| * {@link MathContext#ENGINEERING}). |
| * @param exround The <code>int</code> specifying the rounding mode |
| * to use. |
| * Use -1 for the default, {@link MathContext#ROUND_HALF_UP}. |
| * @return A <code>String</code> representing this |
| * <code>BigDecimal</code>, 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=(int)-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((java.lang.Object)a,0,(java.lang.Object)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((java.lang.Object)a,0,(java.lang.Object)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((java.lang.Object)a,0,(java.lang.Object)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((java.lang.Object)a,p+2,(java.lang.Object)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 <code>BigDecimal</code>. |
| * This hashcode is suitable for use by the |
| * <code>java.util.Hashtable</code> class. |
| * <p> |
| * Note that two <code>BigDecimal</code> objects are only guaranteed |
| * to produce the same hashcode if they are exactly equal (that is, |
| * the <code>String</code> representations of the |
| * <code>BigDecimal</code> numbers are identical -- they have the same |
| * characters in the same sequence). |
| * |
| * @return An <code>int</code> that is the hashcode for <code>this</code>. |
| * @stable ICU 2.0 |
| */ |
| |
| 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 <code>BigDecimal</code> to an <code>int</code>. |
| * If the <code>BigDecimal</code> has a non-zero decimal part it is |
| * discarded. If the <code>BigDecimal</code> is out of the possible |
| * range for an <code>int</code> (32-bit signed integer) result then |
| * only the low-order 32 bits are used. (That is, the number may be |
| * <i>decapitated</i>.) To avoid unexpected errors when these |
| * conditions occur, use the {@link #intValueExact} method. |
| * |
| * @return An <code>int</code> converted from <code>this</code>, |
| * truncated and decapitated if necessary. |
| * @stable ICU 2.0 |
| */ |
| |
| public int intValue(){ |
| return toBigInteger().intValue(); |
| } |
| |
| /** |
| * Converts this <code>BigDecimal</code> to an <code>int</code>. |
| * If the <code>BigDecimal</code> has a non-zero decimal part or is |
| * out of the possible range for an <code>int</code> (32-bit signed |
| * integer) result then an <code>ArithmeticException</code> is thrown. |
| * |
| * @return An <code>int</code> equal in value to <code>this</code>. |
| * @throws ArithmeticException if <code>this</code> has a non-zero |
| * decimal part, or will not fit in an |
| * <code>int</code>. |
| * @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<this<1 |
| useexp=0; |
| } |
| else |
| {/* >=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 (int)-result; |
| } |
| |
| /** |
| * Converts this <code>BigDecimal</code> to a <code>long</code>. |
| * If the <code>BigDecimal</code> has a non-zero decimal part it is |
| * discarded. If the <code>BigDecimal</code> is out of the possible |
| * range for a <code>long</code> (64-bit signed integer) result then |
| * only the low-order 64 bits are used. (That is, the number may be |
| * <i>decapitated</i>.) To avoid unexpected errors when these |
| * conditions occur, use the {@link #longValueExact} method. |
| * |
| * @return A <code>long</code> converted from <code>this</code>, |
| * truncated and decapitated if necessary. |
| * @stable ICU 2.0 |
| */ |
| |
| public long longValue(){ |
| return toBigInteger().longValue(); |
| } |
| |
| /** |
| * Converts this <code>BigDecimal</code> to a <code>long</code>. |
| * If the <code>BigDecimal</code> has a non-zero decimal part or is |
| * out of the possible range for a <code>long</code> (64-bit signed |
| * integer) result then an <code>ArithmeticException</code> is thrown. |
| * |
| * @return A <code>long</code> equal in value to <code>this</code>. |
| * @throws ArithmeticException if <code>this</code> has a non-zero |
| * decimal part, or will not fit in a |
| * <code>long</code>. |
| * @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<this<1 |
| useexp=0; |
| } |
| else |
| {/* >=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=(long)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 (long)-result; |
| } |
| |
| /** |
| * Returns a plain <code>BigDecimal</code> whose decimal point has |
| * been moved to the left by a specified number of positions. |
| * The parameter, <code>n</code>, specifies the number of positions to |
| * move the decimal point. |
| * That is, if <code>n</code> is 0 or positive, the number returned is |
| * given by: |
| * <p><code> |
| * this.multiply(TEN.pow(new BigDecimal(-n))) |
| * </code> |
| * <p> |
| * <code>n</code> may be negative, in which case the method returns |
| * the same result as <code>movePointRight(-n)</code>. |
| * |
| * @param n The <code>int</code> specifying the number of places to |
| * move the decimal point leftwards. |
| * @return A <code>BigDecimal</code> derived from |
| * <code>this</code>, with the decimal point moved |
| * <code>n</code> 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 <code>BigDecimal</code> whose decimal point has |
| * been moved to the right by a specified number of positions. |
| * The parameter, <code>n</code>, specifies the number of positions to |
| * move the decimal point. |
| * That is, if <code>n</code> is 0 or positive, the number returned is |
| * given by: |
| * <p><code> |
| * this.multiply(TEN.pow(new BigDecimal(n))) |
| * </code> |
| * <p> |
| * <code>n</code> may be negative, in which case the method returns |
| * the same result as <code>movePointLeft(-n)</code>. |
| * |
| * @param n The <code>int</code> specifying the number of places to |
| * move the decimal point rightwards. |
| * @return A <code>BigDecimal</code> derived from |
| * <code>this</code>, with the decimal point moved |
| * <code>n</code> 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 <code>BigDecimal</code>. |
| * Returns a non-negative <code>int</code> 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 <code>int</code> whose value is the scale of this |
| * <code>BigDecimal</code>. |
| * @stable ICU 2.0 |
| */ |
| |
| public int scale(){ |
| if (exp>=0) |
| return 0; // scale can never be negative |
| return (int)-exp; |
| } |
| |
| /** |
| * Returns a plain <code>BigDecimal</code> with a given scale. |
| * <p> |
| * 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 |
| * <code>BigDecimal</code> then trailing zeros will be added to the |
| * decimal part as necessary. |
| * <p> |
| * If the given scale is less than the length of the decimal part (the |
| * scale) of this <code>BigDecimal</code> then trailing digits |
| * will be removed, and in this case an |
| * <code>ArithmeticException</code> is thrown if any discarded digits |
| * are non-zero. |
| * <p> |
| * The same as {@link #setScale(int, int)}, where the first parameter |
| * is the scale, and the second is |
| * <code>MathContext.ROUND_UNNECESSARY</code>. |
| * |
| * @param scale The <code>int</code> specifying the scale of the |
| * resulting <code>BigDecimal</code>. |
| * @return A plain <code>BigDecimal</code> with the given scale. |
| * @throws ArithmeticException if <code>scale</code> 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 <code>BigDecimal</code> with a given scale. |
| * <p> |
| * 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 |
| * <code>BigDecimal</code> then trailing zeros will be added to the |
| * decimal part as necessary. |
| * <p> |
| * If the given scale is less than the length of the decimal part (the |
| * scale) of this <code>BigDecimal</code> 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 <code>IllegalArgumentException</code> is thrown if |
| * <code>round</code> is not a valid rounding mode. |
| * <p> |
| * If <code>round</code> is <code>MathContext.ROUND_UNNECESSARY</code>, |
| * an <code>ArithmeticException</code> is thrown if any discarded |
| * digits are non-zero. |
| * |
| * @param scale The <code>int</code> specifying the scale of the |
| * resulting <code>BigDecimal</code>. |
| * @param round The <code>int</code> rounding mode to be used for |
| * the division (see the {@link MathContext} class). |
| * @return A plain <code>BigDecimal</code> with the given scale. |
| * @throws IllegalArgumentException if <code>round</code> is not a |
| * valid rounding mode. |
| * @throws ArithmeticException if <code>scale</code> is negative. |
| * @throws ArithmeticException if <code>round</code> is |
| * <code>MathContext.ROUND_UNNECESSARY</code>, 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=(int)-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!=((int)-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 <code>BigDecimal</code> to a <code>short</code>. |
| * If the <code>BigDecimal</code> has a non-zero decimal part or is |
| * out of the possible range for a <code>short</code> (16-bit signed |
| * integer) result then an <code>ArithmeticException</code> is thrown. |
| * |
| * @return A <code>short</code> equal in value to <code>this</code>. |
| * @throws ArithmeticException if <code>this</code> has a non-zero |
| * decimal part, or will not fit in a |
| * <code>short</code>. |
| * @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 <code>BigDecimal</code>, as an |
| * <code>int</code>. |
| * This returns the <i>signum</i> function value that represents the |
| * sign of this <code>BigDecimal</code>. |
| * That is, -1 if the <code>BigDecimal</code> is negative, 0 if it is |
| * numerically equal to zero, or 1 if it is positive. |
| * |
| * @return An <code>int</code> which is -1 if the |
| * <code>BigDecimal</code> is negative, 0 if it is |
| * numerically equal to zero, or 1 if it is positive. |
| * @stable ICU 2.0 |
| */ |
| |
| public int signum(){ |
| return (int)this.ind; // [note this assumes values for ind.] |
| } |
| |
| //#if defined(FOUNDATION10) |
| //#else |
| /** |
| * Converts this <code>BigDecimal</code> to a |
| * <code>java.math.BigDecimal</code>. |
| * <p> |
| * This is an exact conversion; the result is the same as if the |
| * <code>BigDecimal</code> were formatted as a plain number without |
| * any rounding or exponent and then the |
| * <code>java.math.BigDecimal(java.lang.String)</code> constructor |
| * were used to construct the result. |
| * <p> |
| * <i>(Note: this method is provided only in the |
| * <code>com.ibm.icu.math</code> version of the BigDecimal class. |
| * It would not be present in a <code>java.math</code> version.)</i> |
| * |
| * @return The <code>java.math.BigDecimal</code> equal in value |
| * to this <code>BigDecimal</code>. |
| * @stable ICU 2.0 |
| */ |
| |
| public java.math.BigDecimal toBigDecimal(){ |
| return new java.math.BigDecimal(this.unscaledValue(),this.scale()); |
| } |
| //#endif |
| |
| /** |
| * Converts this <code>BigDecimal</code> to a |
| * <code>java.math.BigInteger</code>. |
| * <p> |
| * Any decimal part is truncated (discarded). |
| * If an exception is desired should the decimal part be non-zero, |
| * use {@link #toBigIntegerExact()}. |
| * |
| * @return The <code>java.math.BigInteger</code> equal in value |
| * to the integer part of this <code>BigDecimal</code>. |
| * @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 (((int)-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((java.lang.Object)res.mant,0,(java.lang.Object)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 <code>BigDecimal</code> to a |
| * <code>java.math.BigInteger</code>. |
| * <p> |
| * An exception is thrown if the decimal part (if any) is non-zero. |
| * |
| * @return The <code>java.math.BigInteger</code> equal in value |
| * to the integer part of this <code>BigDecimal</code>. |
| * @throws ArithmeticException if <code>this</code> 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 <code>BigDecimal</code> as a character array. |
| * The result of this method is the same as using the |
| * sequence <code>toString().toCharArray()</code>, but avoids creating |
| * the intermediate <code>String</code> and <code>char[]</code> |
| * objects. |
| * |
| * @return The <code>char[]</code> array corresponding to this |
| * <code>BigDecimal</code>. |
| * @stable ICU 2.0 |
| */ |
| |
| public char[] toCharArray(){ |
| return layout(); |
| } |
| |
| /** |
| * Returns the <code>BigDecimal</code> as a <code>String</code>. |
| * This returns a <code>String</code> that exactly represents this |
| * <code>BigDecimal</code>, as defined in the decimal documentation |
| * (see {@link BigDecimal class header}). |
| * <p> |
| * By definition, using the {@link #BigDecimal(String)} constructor |
| * on the result <code>String</code> will create a |
| * <code>BigDecimal</code> that is exactly equal to the original |
| * <code>BigDecimal</code>. |
| * |
| * @return The <code>String</code> exactly corresponding to this |
| * <code>BigDecimal</code>. |
| * @see #format(int, int) |
| * @see #format(int, int, int, int, int, int) |
| * @see #toCharArray() |
| * @stable ICU 2.0 |
| */ |
| |
| public java.lang.String toString(){ |
| return new java.lang.String(layout()); |
| } |
| |
| /** |
| * Returns the number as a <code>BigInteger</code> 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 <code>BigInteger</code>. |
| * |
| * @return The <code>java.math.BigInteger</code> equal in value to |
| * this <code>BigDecimal</code> multiplied by ten to the |
| * power of <code>this.scale()</code>. |
| * @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 <code>double</code> to a <code>BigDecimal</code>. |
| * <p> |
| * Returns a <code>BigDecimal</code> 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 <code>NumberFormatException</code> is thrown. |
| * <p> |
| * The number is constructed as though <code>num</code> had been |
| * converted to a <code>String</code> using the |
| * <code>Double.toString()</code> method and the |
| * {@link #BigDecimal(java.lang.String)} constructor had then been used. |
| * This is typically not an exact conversion. |
| * |
| * @param dub The <code>double</code> to be translated. |
| * @return The <code>BigDecimal</code> equal in value to |
| * <code>dub</code>. |
| * @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 <code>long</code> to a <code>BigDecimal</code>. |
| * That is, returns a plain <code>BigDecimal</code> whose value is |
| * equal to the given <code>long</code>. |
| * |
| * @param lint The <code>long</code> to be translated. |
| * @return The <code>BigDecimal</code> equal in value to |
| * <code>lint</code>. |
| * @stable ICU 2.0 |
| */ |
| |
| public static com.ibm.icu.math.BigDecimal valueOf(long lint){ |
| return valueOf(lint,0); |
| } |
| |
| /** |
| * Translates a <code>long</code> to a <code>BigDecimal</code> with a |
| * given scale. |
| * That is, returns a plain <code>BigDecimal</code> whose unscaled |
| * value is equal to the given <code>long</code>, adjusted by the |
| * second parameter, <code>scale</code>. |
| * <p> |
| * The result is given by: |
| * <p><code> |
| * (new BigDecimal(lint)).divide(TEN.pow(new BigDecimal(scale))) |
| * </code> |
| * <p> |
| * A <code>NumberFormatException</code> is thrown if <code>scale</code> |
| * is negative. |
| * |
| * @param lint The <code>long</code> to be translated. |
| * @param scale The <code>int</code> scale to be applied. |
| * @return The <code>BigDecimal</code> equal in value to |
| * <code>lint</code>. |
| * @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=(int)-scale; // exponent is -scale |
| return res; |
| } |
| |
| /* ---------------------------------------------------------------- */ |
| /* Private methods */ |
| /* ---------------------------------------------------------------- */ |
| |
| /* <sgml> Return char array value of a BigDecimal (conversion from |
| BigDecimal to laid-out canonical char array). |
| <p>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). |
| <p>We must not alter the mantissa, here. |
| <p>'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. |
| </sgml> */ |
| |
| private char[] layout(){ |
| char cmant[]; |
| int i=0; |
| java.lang.StringBuffer 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]+((int)('0'))); |
| } |
| }/*i*/ |
| |
| if (form!=com.ibm.icu.math.MathContext.PLAIN) |
| {/* exponential notation needed */ |
| sb=new java.lang.StringBuffer(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=(int)-euse; |
| } |
| else |
| csign='+'; |
| sb.append('E').append(csign).append(euse); |
| } |
| rec=new char[sb.length()]; |
| Utility.getChars(sb, 0,sb.length(),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((java.lang.Object)cmant,0,(java.lang.Object)rec,1,cmant.length); |
| return rec; |
| } |
| |
| /* Need a '.' and/or some zeros */ |
| needsign=(int)((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=(int)-mag;i=needsign+2;for(;$20>0;$20--,i++){ // maybe none |
| rec[i]='0'; |
| } |
| }/*i*/ |
| java.lang.System.arraycopy((java.lang.Object)cmant,0,(java.lang.Object)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((java.lang.Object)cmant,0,(java.lang.Object)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((java.lang.Object)cmant,0,(java.lang.Object)rec,needsign,mag); |
| rec[needsign+mag]='.'; |
| java.lang.System.arraycopy((java.lang.Object)cmant,mag,(java.lang.Object)rec,(needsign+mag)+1,cmant.length-mag); |
| return rec; |
| } |
| |
| /* <sgml> Checks a BigDecimal argument to ensure it's a true integer |
| in a given range. |
| <p>If OK, returns it as an int. </sgml> */ |
| // [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; |
| } |
| |
| /* <sgml> Carry out division operations. </sgml> */ |
| /* |
| 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=ca*10/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!=((int)-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=(int)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,(int)-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((java.lang.Object)var1,start,(java.lang.Object)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 (((int)-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((java.lang.Object)var1,0,(java.lang.Object)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-((((int)-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!=((int)-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((java.lang.Object)res.mant,0,(java.lang.Object)newmant,0,have); |
| res.mant=newmant; |
| } |
| return res.finish(set,true); |
| } |
| |
| |
| /* <sgml> Report a conversion exception. </sgml> */ |
| |
| private void bad(char s[]){ |
| throw new java.lang.NumberFormatException("Not a number:"+" "+java.lang.String.valueOf(s)); |
| } |
| |
| /* <sgml> Report a bad argument to a method. </sgml> |
| 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); |
| } |
| |
| /* <sgml> Extend byte array to given length, padding with 0s. If no |
| extension is required then return the same array. </sgml> |
| |
| 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((java.lang.Object)inarr,0,(java.lang.Object)newarr,0,inarr.length); |
| // 0 padding is carried out by the JVM on allocation initialization |
| return newarr; |
| } |
| |
| /* <sgml> Add or subtract two >=0 integers in byte arrays |
| <p>This routine performs the calculation: |
| <pre> |
| C=A+(B*M) |
| </pre> |
| Where M is in the range -9 through +9 |
| <p> |
| 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=(byte[])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=(byte[])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((java.lang.Object)reb,0,(java.lang.Object)newarr,1,maxarr+1); |
| return newarr; |
| } |
| |
| /* <sgml> Initializer for digit array properties (lookaside). </sgml> |
| 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; |
| } |
| |
| /* <sgml> Create a copy of BigDecimal object for local use. |
| <p>This does NOT make a copy of the mantissa array. |
| </sgml> |
| 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; |
| } |
| |
| /* <sgml> Check one or two numbers for lost digits. </sgml> |
| 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()); |
| } |
| |
| /* <sgml> Round to specified digits, if necessary. </sgml> |
| 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); |
| } |
| |
| /* <sgml> 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. |
| </sgml> |
| */ |
| |
| 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=(int)ind; // save [assumes -1, 0, 1] |
| oldmant=mant; // save |
| if (len>0) |
| { |
| // remove the unwanted digits |
| mant=new byte[len]; |
| java.lang.System.arraycopy((java.lang.Object)oldmant,0,(java.lang.Object)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))==1) |
| 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=(int)-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((java.lang.Object)newmant,0,(java.lang.Object)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; |
| } |
| |
| /* <sgml> 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 |
| </sgml> */ |
| |
| 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; |
| } |
| |
| /* <sgml> Carry out final checks and canonicalization |
| <p> |
| 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. |
| </sgml> |
| 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((java.lang.Object)this.mant,0,(java.lang.Object)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((java.lang.Object)this.mant,i,(java.lang.Object)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; |
| } |
| } |