/* * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.misc; import sun.misc.FpUtils;import sun.misc.DoubleConsts;import sun.misc.FloatConsts;import java.util.regex.*; public class FormattedFloatingDecimal{ boolean isExceptional; boolean isNegative; int decExponent; // value set at construction, then immutable int decExponentRounded; char digits[]; int nDigits; int bigIntExp; int bigIntNBits; boolean mustSetRoundDir = false; boolean fromHex = false; int roundDir = 0; // set by doubleValue int precision; // number of digits to the right of decimal public enum Form { SCIENTIFIC, COMPATIBLE, DECIMAL_FLOAT, GENERAL }; private Form form; private FormattedFloatingDecimal( boolean negSign, int decExponent, char []digits, int n, boolean e, int precision, Form form ) { isNegative = negSign; isExceptional = e; this.decExponent = decExponent; this.digits = digits; this.nDigits = n; this.precision = precision; this.form = form; } /* * Constants of the implementation * Most are IEEE-754 related. * (There are more really boring constants at the end.) */ static final long signMask = 0x8000000000000000L; static final long expMask = 0x7ff0000000000000L; static final long fractMask= ~(signMask|expMask); static final int expShift = 52; static final int expBias = 1023; static final long fractHOB = ( 1L<<expShift ); // assumed High-Order bit static final long expOne = ((long)expBias)<<expShift; // exponent of 1.0 static final int maxSmallBinExp = 62; static final int minSmallBinExp = -( 63 / 3 ); static final int maxDecimalDigits = 15; static final int maxDecimalExponent = 308; static final int minDecimalExponent = -324; static final int bigDecimalExponent = 324; // i.e. abs(minDecimalExponent) static final long highbyte = 0xff00000000000000L; static final long highbit = 0x8000000000000000L; static final long lowbytes = ~highbyte; static final int singleSignMask = 0x80000000; static final int singleExpMask = 0x7f800000; static final int singleFractMask = ~(singleSignMask|singleExpMask); static final int singleExpShift = 23; static final int singleFractHOB = 1<<singleExpShift; static final int singleExpBias = 127; static final int singleMaxDecimalDigits = 7; static final int singleMaxDecimalExponent = 38; static final int singleMinDecimalExponent = -45; static final int intDecimalDigits = 9; /* * count number of bits from high-order 1 bit to low-order 1 bit, * inclusive. */ private static int countBits( long v ){ // // the strategy is to shift until we get a non-zero sign bit // then shift until we have no bits left, counting the difference. // we do byte shifting as a hack. Hope it helps. // if ( v == 0L ) return 0; while ( ( v & highbyte ) == 0L ){ v <<= 8; } while ( v > 0L ) { // i.e. while ((v&highbit) == 0L ) v <<= 1; } int n = 0; while (( v & lowbytes ) != 0L ){ v <<= 8; n += 8; } while ( v != 0L ){ v <<= 1; n += 1; } return n; } /* * Keep big powers of 5 handy for future reference. */ private static FDBigInt b5p[]; private static synchronized FDBigInt big5pow( int p ){ assert p >= 0 : p; // negative power of 5 if ( b5p == null ){ b5p = new FDBigInt[ p+1 ]; }else if (b5p.length <= p ){ FDBigInt t[] = new FDBigInt[ p+1 ]; System.arraycopy( b5p, 0, t, 0, b5p.length ); b5p = t; } if ( b5p[p] != null ) return b5p[p]; else if ( p < small5pow.length ) return b5p[p] = new FDBigInt( small5pow[p] ); else if ( p < long5pow.length ) return b5p[p] = new FDBigInt( long5pow[p] ); else { // construct the value. // recursively. int q, r; // in order to compute 5^p, // compute its square root, 5^(p/2) and square. // or, let q = p / 2, r = p -q, then // 5^p = 5^(q+r) = 5^q * 5^r q = p >> 1; r = p - q; FDBigInt bigq = b5p[q]; if ( bigq == null ) bigq = big5pow ( q ); if ( r < small5pow.length ){ return (b5p[p] = bigq.mult( small5pow[r] ) ); }else{ FDBigInt bigr = b5p[ r ]; if ( bigr == null ) bigr = big5pow( r ); return (b5p[p] = bigq.mult( bigr ) ); } } } // // a common operation // private static FDBigInt multPow52( FDBigInt v, int p5, int p2 ){ if ( p5 != 0 ){ if ( p5 < small5pow.length ){ v = v.mult( small5pow[p5] ); } else { v = v.mult( big5pow( p5 ) ); } } if ( p2 != 0 ){ v.lshiftMe( p2 ); } return v; } // // another common operation // private static FDBigInt constructPow52( int p5, int p2 ){ FDBigInt v = new FDBigInt( big5pow( p5 ) ); if ( p2 != 0 ){ v.lshiftMe( p2 ); } return v; } /* * Make a floating double into a FDBigInt. * This could also be structured as a FDBigInt * constructor, but we'd have to build a lot of knowledge * about floating-point representation into it, and we don't want to. * * AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES * bigIntExp and bigIntNBits * */ private FDBigInt doubleToBigInt( double dval ){ long lbits = Double.doubleToLongBits( dval ) & ~signMask; int binexp = (int)(lbits >>> expShift); lbits &= fractMask; if ( binexp > 0 ){ lbits |= fractHOB; } else { assert lbits != 0L : lbits; // doubleToBigInt(0.0) binexp +=1; while ( (lbits & fractHOB ) == 0L){ lbits <<= 1; binexp -= 1; } } binexp -= expBias; int nbits = countBits( lbits ); /* * We now know where the high-order 1 bit is, * and we know how many there are. */ int lowOrderZeros = expShift+1-nbits; lbits >>>= lowOrderZeros; bigIntExp = binexp+1-nbits; bigIntNBits = nbits; return new FDBigInt( lbits ); } /* * Compute a number that is the ULP of the given value, * for purposes of addition/subtraction. Generally easy. * More difficult if subtracting and the argument * is a normalized a power of 2, as the ULP changes at these points. */ private static double ulp( double dval, boolean subtracting ){ long lbits = Double.doubleToLongBits( dval ) & ~signMask; int binexp = (int)(lbits >>> expShift); double ulpval; if ( subtracting && ( binexp >= expShift ) && ((lbits&fractMask) == 0L) ){ // for subtraction from normalized, powers of 2, // use next-smaller exponent binexp -= 1; } if ( binexp > expShift ){ ulpval = Double.longBitsToDouble( ((long)(binexp-expShift))<<expShift ); } else if ( binexp == 0 ){ ulpval = Double.MIN_VALUE; } else { ulpval = Double.longBitsToDouble( 1L<<(binexp-1) ); } if ( subtracting ) ulpval = - ulpval; return ulpval; } /* * Round a double to a float. * In addition to the fraction bits of the double, * look at the class instance variable roundDir, * which should help us avoid double-rounding error. * roundDir was set in hardValueOf if the estimate was * close enough, but not exact. It tells us which direction * of rounding is preferred. */ float stickyRound( double dval ){ long lbits = Double.doubleToLongBits( dval ); long binexp = lbits & expMask; if ( binexp == 0L || binexp == expMask ){ // what we have here is special. // don't worry, the right thing will happen. return (float) dval; } lbits += (long)roundDir; // hack-o-matic. return (float)Double.longBitsToDouble( lbits ); } /* * This is the easy subcase -- * all the significant bits, after scaling, are held in lvalue. * negSign and decExponent tell us what processing and scaling * has already been done. Exceptional cases have already been * stripped out. * In particular: * lvalue is a finite number (not Inf, nor NaN) * lvalue > 0L (not zero, nor negative). * * The only reason that we develop the digits here, rather than * calling on Long.toString() is that we can do it a little faster, * and besides want to treat trailing 0s specially. If Long.toString * changes, we should re-evaluate this strategy! */ private void developLongDigits( int decExponent, long lvalue, long insignificant ){ char digits[]; int ndigits; int digitno; int c; // // Discard non-significant low-order bits, while rounding, // up to insignificant value. int i; for ( i = 0; insignificant >= 10L; i++ ) insignificant /= 10L; if ( i != 0 ){ long pow10 = long5pow[i] << i; // 10^i == 5^i * 2^i; long residue = lvalue % pow10; lvalue /= pow10; decExponent += i; if ( residue >= (pow10>>1) ){ // round up based on the low-order bits we're discarding lvalue++; } } if ( lvalue <= Integer.MAX_VALUE ){ assert lvalue > 0L : lvalue; // lvalue <= 0 // even easier subcase! // can do int arithmetic rather than long! int ivalue = (int)lvalue; ndigits = 10; digits = (char[])(perThreadBuffer.get()); digitno = ndigits-1; c = ivalue%10; ivalue /= 10; while ( c == 0 ){ decExponent++; c = ivalue%10; ivalue /= 10; } while ( ivalue != 0){ digits[digitno--] = (char)(c+'0'); decExponent++; c = ivalue%10; ivalue /= 10; } digits[digitno] = (char)(c+'0'); } else { // same algorithm as above (same bugs, too ) // but using long arithmetic. ndigits = 20; digits = (char[])(perThreadBuffer.get()); digitno = ndigits-1; c = (int)(lvalue%10L); lvalue /= 10L; while ( c == 0 ){ decExponent++; c = (int)(lvalue%10L); lvalue /= 10L; } while ( lvalue != 0L ){ digits[digitno--] = (char)(c+'0'); decExponent++; c = (int)(lvalue%10L); lvalue /= 10; } digits[digitno] = (char)(c+'0'); } char result []; ndigits -= digitno; result = new char[ ndigits ]; System.arraycopy( digits, digitno, result, 0, ndigits ); this.digits = result; this.decExponent = decExponent+1; this.nDigits = ndigits; } // // add one to the least significant digit. // in the unlikely event there is a carry out, // deal with it. // assert that this will only happen where there // is only one digit, e.g. (float)1e-44 seems to do it. // private void roundup(){ int i; int q = digits[ i = (nDigits-1)]; if ( q == '9' ){ while ( q == '9' && i > 0 ){ digits[i] = '0'; q = digits[--i]; } if ( q == '9' ){ // carryout! High-order 1, rest 0s, larger exp. decExponent += 1; digits[0] = '1'; return; } // else fall through. } digits[i] = (char)(q+1); } // Given the desired number of digits predict the result's exponent. private int checkExponent(int length) { if (length >= nDigits || length < 0) return decExponent; for (int i = 0; i < length; i++) if (digits[i] != '9') // a '9' anywhere in digits will absorb the round return decExponent; return decExponent + (digits[length] >= '5' ? 1 : 0); } // Unlike roundup(), this method does not modify digits. It also // rounds at a particular precision. private char [] applyPrecision(int length) { char [] result = new char[nDigits]; for (int i = 0; i < result.length; i++) result[i] = '0'; if (length >= nDigits || length < 0) { // no rounding necessary System.arraycopy(digits, 0, result, 0, nDigits); return result; } if (length == 0) { // only one digit (0 or 1) is returned because the precision // excludes all significant digits if (digits[0] >= '5') { result[0] = '1'; } return result; } int i = length; int q = digits[i]; if (q >= '5' && i > 0) { q = digits[--i]; if ( q == '9' ) { while ( q == '9' && i > 0 ){ q = digits[--i]; } if ( q == '9' ){ // carryout! High-order 1, rest 0s, larger exp. result[0] = '1'; return result; } } result[i] = (char)(q + 1); } while (--i >= 0) { result[i] = digits[i]; } return result; } /* * FIRST IMPORTANT CONSTRUCTOR: DOUBLE */ public FormattedFloatingDecimal( double d ) { this(d, Integer.MAX_VALUE, Form.COMPATIBLE); } public FormattedFloatingDecimal( double d, int precision, Form form ) { long dBits = Double.doubleToLongBits( d ); long fractBits; int binExp; int nSignificantBits; this.precision = precision; this.form = form; // discover and delete sign if ( (dBits&signMask) != 0 ){ isNegative = true; dBits ^= signMask; } else { isNegative = false; } // Begin to unpack // Discover obvious special cases of NaN and Infinity. binExp = (int)( (dBits&expMask) >> expShift ); fractBits = dBits&fractMask; if ( binExp == (int)(expMask>>expShift) ) { isExceptional = true; if ( fractBits == 0L ){ digits = infinity; } else { digits = notANumber; isNegative = false; // NaN has no sign! }Lines 1–500 of 1767. Load more
/* * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.misc; import sun.misc.FpUtils; import sun.misc.DoubleConsts; import sun.misc.FloatConsts; import java.util.regex.*; public class FormattedFloatingDecimal{ boolean isExceptional; boolean isNegative; int decExponent; // value set at construction, then immutable int decExponentRounded; char digits[]; int nDigits; int bigIntExp; int bigIntNBits; boolean mustSetRoundDir = false; boolean fromHex = false; int roundDir = 0; // set by doubleValue int precision; // number of digits to the right of decimal public enum Form { SCIENTIFIC, COMPATIBLE, DECIMAL_FLOAT, GENERAL }; private Form form; private FormattedFloatingDecimal( boolean negSign, int decExponent, char []digits, int n, boolean e, int precision, Form form ) { isNegative = negSign; isExceptional = e; this.decExponent = decExponent; this.digits = digits; this.nDigits = n; this.precision = precision; this.form = form; } /* * Constants of the implementation * Most are IEEE-754 related. * (There are more really boring constants at the end.) */ static final long signMask = 0x8000000000000000L; static final long expMask = 0x7ff0000000000000L; static final long fractMask= ~(signMask|expMask); static final int expShift = 52; static final int expBias = 1023; static final long fractHOB = ( 1L<<expShift ); // assumed High-Order bit static final long expOne = ((long)expBias)<<expShift; // exponent of 1.0 static final int maxSmallBinExp = 62; static final int minSmallBinExp = -( 63 / 3 ); static final int maxDecimalDigits = 15; static final int maxDecimalExponent = 308; static final int minDecimalExponent = -324; static final int bigDecimalExponent = 324; // i.e. abs(minDecimalExponent) static final long highbyte = 0xff00000000000000L; static final long highbit = 0x8000000000000000L; static final long lowbytes = ~highbyte; static final int singleSignMask = 0x80000000; static final int singleExpMask = 0x7f800000; static final int singleFractMask = ~(singleSignMask|singleExpMask); static final int singleExpShift = 23; static final int singleFractHOB = 1<<singleExpShift; static final int singleExpBias = 127; static final int singleMaxDecimalDigits = 7; static final int singleMaxDecimalExponent = 38; static final int singleMinDecimalExponent = -45; static final int intDecimalDigits = 9; /* * count number of bits from high-order 1 bit to low-order 1 bit, * inclusive. */ private static int countBits( long v ){ // // the strategy is to shift until we get a non-zero sign bit // then shift until we have no bits left, counting the difference. // we do byte shifting as a hack. Hope it helps. // if ( v == 0L ) return 0; while ( ( v & highbyte ) == 0L ){ v <<= 8; } while ( v > 0L ) { // i.e. while ((v&highbit) == 0L ) v <<= 1; } int n = 0; while (( v & lowbytes ) != 0L ){ v <<= 8; n += 8; } while ( v != 0L ){ v <<= 1; n += 1; } return n; } /* * Keep big powers of 5 handy for future reference. */ private static FDBigInt b5p[]; private static synchronized FDBigInt big5pow( int p ){ assert p >= 0 : p; // negative power of 5 if ( b5p == null ){ b5p = new FDBigInt[ p+1 ]; }else if (b5p.length <= p ){ FDBigInt t[] = new FDBigInt[ p+1 ]; System.arraycopy( b5p, 0, t, 0, b5p.length ); b5p = t; } if ( b5p[p] != null ) return b5p[p]; else if ( p < small5pow.length ) return b5p[p] = new FDBigInt( small5pow[p] ); else if ( p < long5pow.length ) return b5p[p] = new FDBigInt( long5pow[p] ); else { // construct the value. // recursively. int q, r; // in order to compute 5^p, // compute its square root, 5^(p/2) and square. // or, let q = p / 2, r = p -q, then // 5^p = 5^(q+r) = 5^q * 5^r q = p >> 1; r = p - q; FDBigInt bigq = b5p[q]; if ( bigq == null ) bigq = big5pow ( q ); if ( r < small5pow.length ){ return (b5p[p] = bigq.mult( small5pow[r] ) ); }else{ FDBigInt bigr = b5p[ r ]; if ( bigr == null ) bigr = big5pow( r ); return (b5p[p] = bigq.mult( bigr ) ); } } } // // a common operation // private static FDBigInt multPow52( FDBigInt v, int p5, int p2 ){ if ( p5 != 0 ){ if ( p5 < small5pow.length ){ v = v.mult( small5pow[p5] ); } else { v = v.mult( big5pow( p5 ) ); } } if ( p2 != 0 ){ v.lshiftMe( p2 ); } return v; } // // another common operation // private static FDBigInt constructPow52( int p5, int p2 ){ FDBigInt v = new FDBigInt( big5pow( p5 ) ); if ( p2 != 0 ){ v.lshiftMe( p2 ); } return v; } /* * Make a floating double into a FDBigInt. * This could also be structured as a FDBigInt * constructor, but we'd have to build a lot of knowledge * about floating-point representation into it, and we don't want to. * * AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES * bigIntExp and bigIntNBits * */ private FDBigInt doubleToBigInt( double dval ){ long lbits = Double.doubleToLongBits( dval ) & ~signMask; int binexp = (int)(lbits >>> expShift); lbits &= fractMask; if ( binexp > 0 ){ lbits |= fractHOB; } else { assert lbits != 0L : lbits; // doubleToBigInt(0.0) binexp +=1; while ( (lbits & fractHOB ) == 0L){ lbits <<= 1; binexp -= 1; } } binexp -= expBias; int nbits = countBits( lbits ); /* * We now know where the high-order 1 bit is, * and we know how many there are. */ int lowOrderZeros = expShift+1-nbits; lbits >>>= lowOrderZeros; bigIntExp = binexp+1-nbits; bigIntNBits = nbits; return new FDBigInt( lbits ); } /* * Compute a number that is the ULP of the given value, * for purposes of addition/subtraction. Generally easy. * More difficult if subtracting and the argument * is a normalized a power of 2, as the ULP changes at these points. */ private static double ulp( double dval, boolean subtracting ){ long lbits = Double.doubleToLongBits( dval ) & ~signMask; int binexp = (int)(lbits >>> expShift); double ulpval; if ( subtracting && ( binexp >= expShift ) && ((lbits&fractMask) == 0L) ){ // for subtraction from normalized, powers of 2, // use next-smaller exponent binexp -= 1; } if ( binexp > expShift ){ ulpval = Double.longBitsToDouble( ((long)(binexp-expShift))<<expShift ); } else if ( binexp == 0 ){ ulpval = Double.MIN_VALUE; } else { ulpval = Double.longBitsToDouble( 1L<<(binexp-1) ); } if ( subtracting ) ulpval = - ulpval; return ulpval; } /* * Round a double to a float. * In addition to the fraction bits of the double, * look at the class instance variable roundDir, * which should help us avoid double-rounding error. * roundDir was set in hardValueOf if the estimate was * close enough, but not exact. It tells us which direction * of rounding is preferred. */ float stickyRound( double dval ){ long lbits = Double.doubleToLongBits( dval ); long binexp = lbits & expMask; if ( binexp == 0L || binexp == expMask ){ // what we have here is special. // don't worry, the right thing will happen. return (float) dval; } lbits += (long)roundDir; // hack-o-matic. return (float)Double.longBitsToDouble( lbits ); } /* * This is the easy subcase -- * all the significant bits, after scaling, are held in lvalue. * negSign and decExponent tell us what processing and scaling * has already been done. Exceptional cases have already been * stripped out. * In particular: * lvalue is a finite number (not Inf, nor NaN) * lvalue > 0L (not zero, nor negative). * * The only reason that we develop the digits here, rather than * calling on Long.toString() is that we can do it a little faster, * and besides want to treat trailing 0s specially. If Long.toString * changes, we should re-evaluate this strategy! */ private void developLongDigits( int decExponent, long lvalue, long insignificant ){ char digits[]; int ndigits; int digitno; int c; // // Discard non-significant low-order bits, while rounding, // up to insignificant value. int i; for ( i = 0; insignificant >= 10L; i++ ) insignificant /= 10L; if ( i != 0 ){ long pow10 = long5pow[i] << i; // 10^i == 5^i * 2^i; long residue = lvalue % pow10; lvalue /= pow10; decExponent += i; if ( residue >= (pow10>>1) ){ // round up based on the low-order bits we're discarding lvalue++; } } if ( lvalue <= Integer.MAX_VALUE ){ assert lvalue > 0L : lvalue; // lvalue <= 0 // even easier subcase! // can do int arithmetic rather than long! int ivalue = (int)lvalue; ndigits = 10; digits = (char[])(perThreadBuffer.get()); digitno = ndigits-1; c = ivalue%10; ivalue /= 10; while ( c == 0 ){ decExponent++; c = ivalue%10; ivalue /= 10; } while ( ivalue != 0){ digits[digitno--] = (char)(c+'0'); decExponent++; c = ivalue%10; ivalue /= 10; } digits[digitno] = (char)(c+'0'); } else { // same algorithm as above (same bugs, too ) // but using long arithmetic. ndigits = 20; digits = (char[])(perThreadBuffer.get()); digitno = ndigits-1; c = (int)(lvalue%10L); lvalue /= 10L; while ( c == 0 ){ decExponent++; c = (int)(lvalue%10L); lvalue /= 10L; } while ( lvalue != 0L ){ digits[digitno--] = (char)(c+'0'); decExponent++; c = (int)(lvalue%10L); lvalue /= 10; } digits[digitno] = (char)(c+'0'); } char result []; ndigits -= digitno; result = new char[ ndigits ]; System.arraycopy( digits, digitno, result, 0, ndigits ); this.digits = result; this.decExponent = decExponent+1; this.nDigits = ndigits; } // // add one to the least significant digit. // in the unlikely event there is a carry out, // deal with it. // assert that this will only happen where there // is only one digit, e.g. (float)1e-44 seems to do it. // private void roundup(){ int i; int q = digits[ i = (nDigits-1)]; if ( q == '9' ){ while ( q == '9' && i > 0 ){ digits[i] = '0'; q = digits[--i]; } if ( q == '9' ){ // carryout! High-order 1, rest 0s, larger exp. decExponent += 1; digits[0] = '1'; return; } // else fall through. } digits[i] = (char)(q+1); } // Given the desired number of digits predict the result's exponent. private int checkExponent(int length) { if (length >= nDigits || length < 0) return decExponent; for (int i = 0; i < length; i++) if (digits[i] != '9') // a '9' anywhere in digits will absorb the round return decExponent; return decExponent + (digits[length] >= '5' ? 1 : 0); } // Unlike roundup(), this method does not modify digits. It also // rounds at a particular precision. private char [] applyPrecision(int length) { char [] result = new char[nDigits]; for (int i = 0; i < result.length; i++) result[i] = '0'; if (length >= nDigits || length < 0) { // no rounding necessary System.arraycopy(digits, 0, result, 0, nDigits); return result; } if (length == 0) { // only one digit (0 or 1) is returned because the precision // excludes all significant digits if (digits[0] >= '5') { result[0] = '1'; } return result; } int i = length; int q = digits[i]; if (q >= '5' && i > 0) { q = digits[--i]; if ( q == '9' ) { while ( q == '9' && i > 0 ){ q = digits[--i]; } if ( q == '9' ){ // carryout! High-order 1, rest 0s, larger exp. result[0] = '1'; return result; } } result[i] = (char)(q + 1); } while (--i >= 0) { result[i] = digits[i]; } return result; } /* * FIRST IMPORTANT CONSTRUCTOR: DOUBLE */ public FormattedFloatingDecimal( double d ) { this(d, Integer.MAX_VALUE, Form.COMPATIBLE); } public FormattedFloatingDecimal( double d, int precision, Form form ) { long dBits = Double.doubleToLongBits( d ); long fractBits; int binExp; int nSignificantBits; this.precision = precision; this.form = form; // discover and delete sign if ( (dBits&signMask) != 0 ){ isNegative = true; dBits ^= signMask; } else { isNegative = false; } // Begin to unpack // Discover obvious special cases of NaN and Infinity. binExp = (int)( (dBits&expMask) >> expShift ); fractBits = dBits&fractMask; if ( binExp == (int)(expMask>>expShift) ) { isExceptional = true; if ( fractBits == 0L ){ digits = infinity; } else { digits = notANumber; isNegative = false; // NaN has no sign! }