< prev index next >

src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java

Print this page
rev 55787 : 8228507: Archive FDBigInteger
Reviewed-by: TBD


 114      * Converts a <code>String</code> to a single precision floating point value.
 115      *
 116      * @param s The <code>String</code> to convert.
 117      * @return The single precision value.
 118      * @throws NumberFormatException If the <code>String</code> does not
 119      * represent a properly formatted single precision value.
 120      */
 121     public static float parseFloat(String s) throws NumberFormatException {
 122         return readJavaFormatString(s).floatValue();
 123     }
 124 
 125     /**
 126      * A converter which can process single or double precision floating point
 127      * values into an ASCII <code>String</code> representation.
 128      */
 129     public interface BinaryToASCIIConverter {
 130         /**
 131          * Converts a floating point value into an ASCII <code>String</code>.
 132          * @return The value converted to a <code>String</code>.
 133          */
 134         public String toJavaFormatString();
 135 
 136         /**
 137          * Appends a floating point value to an <code>Appendable</code>.
 138          * @param buf The <code>Appendable</code> to receive the value.
 139          */
 140         public void appendTo(Appendable buf);
 141 
 142         /**
 143          * Retrieves the decimal exponent most closely corresponding to this value.
 144          * @return The decimal exponent.
 145          */
 146         public int getDecimalExponent();
 147 
 148         /**
 149          * Retrieves the value as an array of digits.
 150          * @param digits The digit array.
 151          * @return The number of valid digits copied into the array.
 152          */
 153         public int getDigits(char[] digits);
 154 
 155         /**
 156          * Indicates the sign of the value.
 157          * @return {@code value < 0.0}.
 158          */
 159         public boolean isNegative();
 160 
 161         /**
 162          * Indicates whether the value is either infinite or not a number.
 163          *
 164          * @return <code>true</code> if and only if the value is <code>NaN</code>
 165          * or infinite.
 166          */
 167         public boolean isExceptional();
 168 
 169         /**
 170          * Indicates whether the value was rounded up during the binary to ASCII
 171          * conversion.
 172          *
 173          * @return <code>true</code> if and only if the value was rounded up.
 174          */
 175         public boolean digitsRoundedUp();
 176 
 177         /**
 178          * Indicates whether the binary to ASCII conversion was exact.
 179          *
 180          * @return <code>true</code> if any only if the conversion was exact.
 181          */
 182         public boolean decimalDigitsExact();
 183     }
 184 
 185     /**
 186      * A <code>BinaryToASCIIConverter</code> which represents <code>NaN</code>
 187      * and infinite values.
 188      */
 189     private static class ExceptionalBinaryToASCIIBuffer implements BinaryToASCIIConverter {
 190         private final String image;
 191         private boolean isNegative;
 192 
 193         public ExceptionalBinaryToASCIIBuffer(String image, boolean isNegative) {
 194             this.image = image;
 195             this.isNegative = isNegative;
 196         }
 197 
 198         @Override
 199         public String toJavaFormatString() {
 200             return image;
 201         }
 202 


 304 
 305         @Override
 306         public void appendTo(Appendable buf) {
 307             int len = getChars(buffer);
 308             if (buf instanceof StringBuilder) {
 309                 ((StringBuilder) buf).append(buffer, 0, len);
 310             } else if (buf instanceof StringBuffer) {
 311                 ((StringBuffer) buf).append(buffer, 0, len);
 312             } else {
 313                 assert false;
 314             }
 315         }
 316 
 317         @Override
 318         public int getDecimalExponent() {
 319             return decExponent;
 320         }
 321 
 322         @Override
 323         public int getDigits(char[] digits) {
 324             System.arraycopy(this.digits,firstDigitIndex,digits,0,this.nDigits);
 325             return this.nDigits;
 326         }
 327 
 328         @Override
 329         public boolean isNegative() {
 330             return isNegative;
 331         }
 332 
 333         @Override
 334         public boolean isExceptional() {
 335             return false;
 336         }
 337 
 338         @Override
 339         public boolean digitsRoundedUp() {
 340             return decimalDigitsRoundedUp;
 341         }
 342 
 343         @Override
 344         public boolean decimalDigitsExact() {


 832             } else { //if (exponent >= 52)
 833                 return (int)d;
 834             }
 835         }
 836 
 837         private static int insignificantDigits(int insignificant) {
 838             int i;
 839             for ( i = 0; insignificant >= 10L; i++ ) {
 840                 insignificant /= 10L;
 841             }
 842             return i;
 843         }
 844 
 845         /**
 846          * Calculates
 847          * <pre>
 848          * insignificantDigitsForPow2(v) == insignificantDigits(1L<<v)
 849          * </pre>
 850          */
 851         private static int insignificantDigitsForPow2(int p2) {
 852             if(p2>1 && p2 < insignificantDigitsNumber.length) {
 853                 return insignificantDigitsNumber[p2];
 854             }
 855             return 0;
 856         }
 857 
 858         /**
 859          *  If insignificant==(1L << ixd)
 860          *  i = insignificantDigitsNumber[idx] is the same as:
 861          *  int i;
 862          *  for ( i = 0; insignificant >= 10L; i++ )
 863          *         insignificant /= 10L;
 864          */
 865         private static int[] insignificantDigitsNumber = {
 866             0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3,
 867             4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7,
 868             8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11,
 869             12, 12, 12, 12, 13, 13, 13, 14, 14, 14,
 870             15, 15, 15, 15, 16, 16, 16, 17, 17, 17,
 871             18, 18, 18, 19
 872         };
 873 
 874         // approximately ceil( log2( long5pow[i] ) )
 875         private static final int[] N_5_BITS = {
 876                 0,
 877                 3,
 878                 5,
 879                 7,
 880                 10,
 881                 12,
 882                 14,
 883                 17,
 884                 19,
 885                 21,


1856                     return A2BC_NOT_A_NUMBER;
1857                 }
1858                 // something went wrong, throw exception
1859                 break parseNumber;
1860             } else if(c == 'I') { // Check for Infinity strings
1861                 if((len-i)==INFINITY_LENGTH && in.indexOf(INFINITY_REP,i)==i) {
1862                     return isNegative? A2BC_NEGATIVE_INFINITY : A2BC_POSITIVE_INFINITY;
1863                 }
1864                 // something went wrong, throw exception
1865                 break parseNumber;
1866             } else if (c == '0')  { // check for hexadecimal floating-point number
1867                 if (len > i+1 ) {
1868                     char ch = in.charAt(i+1);
1869                     if (ch == 'x' || ch == 'X' ) { // possible hex string
1870                         return parseHexString(in);
1871                     }
1872                 }
1873             }  // look for and process decimal floating-point string
1874 
1875             char[] digits = new char[ len ];
1876             int    nDigits= 0;
1877             boolean decSeen = false;

1878             int decPt = 0;
1879             int nLeadZero = 0;
1880             int nTrailZero= 0;
1881 
1882         skipLeadingZerosLoop:
1883             while (i < len) {
1884                 c = in.charAt(i);
1885                 if (c == '0') {
1886                     nLeadZero++;
1887                 } else if (c == '.') {
1888                     if (decSeen) {
1889                         // already saw one ., this is the 2nd.
1890                         throw new NumberFormatException("multiple points");
1891                     }
1892                     decPt = i;
1893                     if (signSeen) {
1894                         decPt -= 1;
1895                     }
1896                     decSeen = true;
1897                 } else {
1898                     break skipLeadingZerosLoop;
1899                 }
1900                 i++;


2120                 //
2121                 // There are a number of significand scenarios to consider;
2122                 // letters are used in indicate nonzero digits:
2123                 //
2124                 // 1. 000xxxx       =>      x.xxx   normalized
2125                 //    increase exponent by (number of x's - 1)*4
2126                 //
2127                 // 2. 000xxx.yyyy =>        x.xxyyyy        normalized
2128                 //    increase exponent by (number of x's - 1)*4
2129                 //
2130                 // 3. .000yyy  =>   y.yy    normalized
2131                 //    decrease exponent by (number of zeros + 1)*4
2132                 //
2133                 // 4. 000.00000yyy => y.yy normalized
2134                 //    decrease exponent by (number of zeros to right of point + 1)*4
2135                 //
2136                 // If the significand is exactly zero, return a properly
2137                 // signed zero.
2138                 //
2139 
2140                 String significandString = null;
2141                 int signifLength = 0;
2142                 int exponentAdjust = 0;
2143                 {
2144                     int leftDigits = 0; // number of meaningful digits to
2145                     // left of "decimal" point
2146                     // (leading zeros stripped)
2147                     int rightDigits = 0; // number of digits to right of
2148                     // "decimal" point; leading zeros
2149                     // must always be accounted for
2150                     //
2151                     // The significand is made up of either
2152                     //
2153                     // 1. group 4 entirely (integer portion only)
2154                     //
2155                     // OR
2156                     //
2157                     // 2. the fractional portion from group 7 plus any
2158                     // (optional) integer portions from group 6.
2159                     //
2160                     String group4;
2161                     if ((group4 = m.group(4)) != null) {  // Integer-only significand
2162                         // Leading zeros never matter on the integer portion


2229                     //              -       +0.0            -0.0
2230                     return isNegative ?
2231                               (positiveExponent ? A2BC_NEGATIVE_INFINITY : A2BC_NEGATIVE_ZERO)
2232                             : (positiveExponent ? A2BC_POSITIVE_INFINITY : A2BC_POSITIVE_ZERO);
2233 
2234                 }
2235 
2236                 long rawExponent =
2237                         (positiveExponent ? 1L : -1L) * // exponent sign
2238                                 unsignedRawExponent;            // exponent magnitude
2239 
2240                 // Calculate partially adjusted exponent
2241                 long exponent = rawExponent + exponentAdjust;
2242 
2243                 // Starting copying non-zero bits into proper position in
2244                 // a long; copy explicit bit too; this will be masked
2245                 // later for normal values.
2246 
2247                 boolean round = false;
2248                 boolean sticky = false;
2249                 int nextShift = 0;
2250                 long significand = 0L;
2251                 // First iteration is different, since we only copy
2252                 // from the leading significand bit; one more exponent
2253                 // adjust will be needed...
2254 
2255                 // IMPORTANT: make leadingDigit a long to avoid
2256                 // surprising shift semantics!
2257                 long leadingDigit = getHexDigit(significandString, 0);
2258 
2259                 //
2260                 // Left shift the leading digit (53 - (bit position of
2261                 // leading 1 in digit)); this sets the top bit of the
2262                 // significand to 1.  The nextShift value is adjusted
2263                 // to take into account the number of bit positions of
2264                 // the leadingDigit actually used.  Finally, the
2265                 // exponent is adjusted to normalize the significand
2266                 // as a binary value, not just a hex value.
2267                 //
2268                 if (leadingDigit == 1) {
2269                     significand |= leadingDigit << 52;


2508                     //
2509                     boolean leastZero = ((significand & 1L) == 0L);
2510                     if ((leastZero && round && sticky) ||
2511                             ((!leastZero) && round)) {
2512                         significand++;
2513                     }
2514 
2515                     double value = isNegative ?
2516                             Double.longBitsToDouble(significand | DoubleConsts.SIGN_BIT_MASK) :
2517                             Double.longBitsToDouble(significand );
2518 
2519                     return new PreparedASCIIToBinaryBuffer(value, fValue);
2520                 }
2521             }
2522     }
2523 
2524     /**
2525      * Returns <code>s</code> with any leading zeros removed.
2526      */
2527     static String stripLeadingZeros(String s) {
2528 //        return  s.replaceFirst("^0+", "");
2529         if(!s.isEmpty() && s.charAt(0)=='0') {
2530             for(int i=1; i<s.length(); i++) {
2531                 if(s.charAt(i)!='0') {
2532                     return s.substring(i);
2533                 }
2534             }
2535             return "";
2536         }
2537         return s;
2538     }
2539 
2540     /**
2541      * Extracts a hexadecimal digit from position <code>position</code>
2542      * of string <code>s</code>.
2543      */
2544     static int getHexDigit(String s, int position) {
2545         int value = Character.digit(s.charAt(position), 16);
2546         if (value <= -1 || value >= 16) {
2547             throw new AssertionError("Unexpected failure of digit conversion of " +
2548                                      s.charAt(position));


 114      * Converts a <code>String</code> to a single precision floating point value.
 115      *
 116      * @param s The <code>String</code> to convert.
 117      * @return The single precision value.
 118      * @throws NumberFormatException If the <code>String</code> does not
 119      * represent a properly formatted single precision value.
 120      */
 121     public static float parseFloat(String s) throws NumberFormatException {
 122         return readJavaFormatString(s).floatValue();
 123     }
 124 
 125     /**
 126      * A converter which can process single or double precision floating point
 127      * values into an ASCII <code>String</code> representation.
 128      */
 129     public interface BinaryToASCIIConverter {
 130         /**
 131          * Converts a floating point value into an ASCII <code>String</code>.
 132          * @return The value converted to a <code>String</code>.
 133          */
 134         String toJavaFormatString();
 135 
 136         /**
 137          * Appends a floating point value to an <code>Appendable</code>.
 138          * @param buf The <code>Appendable</code> to receive the value.
 139          */
 140         void appendTo(Appendable buf);
 141 
 142         /**
 143          * Retrieves the decimal exponent most closely corresponding to this value.
 144          * @return The decimal exponent.
 145          */
 146         int getDecimalExponent();
 147 
 148         /**
 149          * Retrieves the value as an array of digits.
 150          * @param digits The digit array.
 151          * @return The number of valid digits copied into the array.
 152          */
 153         int getDigits(char[] digits);
 154 
 155         /**
 156          * Indicates the sign of the value.
 157          * @return {@code value < 0.0}.
 158          */
 159         boolean isNegative();
 160 
 161         /**
 162          * Indicates whether the value is either infinite or not a number.
 163          *
 164          * @return <code>true</code> if and only if the value is <code>NaN</code>
 165          * or infinite.
 166          */
 167         boolean isExceptional();
 168 
 169         /**
 170          * Indicates whether the value was rounded up during the binary to ASCII
 171          * conversion.
 172          *
 173          * @return <code>true</code> if and only if the value was rounded up.
 174          */
 175         boolean digitsRoundedUp();
 176 
 177         /**
 178          * Indicates whether the binary to ASCII conversion was exact.
 179          *
 180          * @return <code>true</code> if any only if the conversion was exact.
 181          */
 182         boolean decimalDigitsExact();
 183     }
 184 
 185     /**
 186      * A <code>BinaryToASCIIConverter</code> which represents <code>NaN</code>
 187      * and infinite values.
 188      */
 189     private static class ExceptionalBinaryToASCIIBuffer implements BinaryToASCIIConverter {
 190         private final String image;
 191         private boolean isNegative;
 192 
 193         public ExceptionalBinaryToASCIIBuffer(String image, boolean isNegative) {
 194             this.image = image;
 195             this.isNegative = isNegative;
 196         }
 197 
 198         @Override
 199         public String toJavaFormatString() {
 200             return image;
 201         }
 202 


 304 
 305         @Override
 306         public void appendTo(Appendable buf) {
 307             int len = getChars(buffer);
 308             if (buf instanceof StringBuilder) {
 309                 ((StringBuilder) buf).append(buffer, 0, len);
 310             } else if (buf instanceof StringBuffer) {
 311                 ((StringBuffer) buf).append(buffer, 0, len);
 312             } else {
 313                 assert false;
 314             }
 315         }
 316 
 317         @Override
 318         public int getDecimalExponent() {
 319             return decExponent;
 320         }
 321 
 322         @Override
 323         public int getDigits(char[] digits) {
 324             System.arraycopy(this.digits, firstDigitIndex, digits, 0, this.nDigits);
 325             return this.nDigits;
 326         }
 327 
 328         @Override
 329         public boolean isNegative() {
 330             return isNegative;
 331         }
 332 
 333         @Override
 334         public boolean isExceptional() {
 335             return false;
 336         }
 337 
 338         @Override
 339         public boolean digitsRoundedUp() {
 340             return decimalDigitsRoundedUp;
 341         }
 342 
 343         @Override
 344         public boolean decimalDigitsExact() {


 832             } else { //if (exponent >= 52)
 833                 return (int)d;
 834             }
 835         }
 836 
 837         private static int insignificantDigits(int insignificant) {
 838             int i;
 839             for ( i = 0; insignificant >= 10L; i++ ) {
 840                 insignificant /= 10L;
 841             }
 842             return i;
 843         }
 844 
 845         /**
 846          * Calculates
 847          * <pre>
 848          * insignificantDigitsForPow2(v) == insignificantDigits(1L<<v)
 849          * </pre>
 850          */
 851         private static int insignificantDigitsForPow2(int p2) {
 852             if (p2 > 1 && p2 < insignificantDigitsNumber.length) {
 853                 return insignificantDigitsNumber[p2];
 854             }
 855             return 0;
 856         }
 857 
 858         /**
 859          *  If insignificant==(1L << ixd)
 860          *  i = insignificantDigitsNumber[idx] is the same as:
 861          *  int i;
 862          *  for ( i = 0; insignificant >= 10L; i++ )
 863          *         insignificant /= 10L;
 864          */
 865         private static final int[] insignificantDigitsNumber = {
 866             0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3,
 867             4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7,
 868             8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11,
 869             12, 12, 12, 12, 13, 13, 13, 14, 14, 14,
 870             15, 15, 15, 15, 16, 16, 16, 17, 17, 17,
 871             18, 18, 18, 19
 872         };
 873 
 874         // approximately ceil( log2( long5pow[i] ) )
 875         private static final int[] N_5_BITS = {
 876                 0,
 877                 3,
 878                 5,
 879                 7,
 880                 10,
 881                 12,
 882                 14,
 883                 17,
 884                 19,
 885                 21,


1856                     return A2BC_NOT_A_NUMBER;
1857                 }
1858                 // something went wrong, throw exception
1859                 break parseNumber;
1860             } else if(c == 'I') { // Check for Infinity strings
1861                 if((len-i)==INFINITY_LENGTH && in.indexOf(INFINITY_REP,i)==i) {
1862                     return isNegative? A2BC_NEGATIVE_INFINITY : A2BC_POSITIVE_INFINITY;
1863                 }
1864                 // something went wrong, throw exception
1865                 break parseNumber;
1866             } else if (c == '0')  { // check for hexadecimal floating-point number
1867                 if (len > i+1 ) {
1868                     char ch = in.charAt(i+1);
1869                     if (ch == 'x' || ch == 'X' ) { // possible hex string
1870                         return parseHexString(in);
1871                     }
1872                 }
1873             }  // look for and process decimal floating-point string
1874 
1875             char[] digits = new char[ len ];

1876             boolean decSeen = false;
1877             int nDigits = 0;
1878             int decPt = 0;
1879             int nLeadZero = 0;
1880             int nTrailZero = 0;
1881 
1882         skipLeadingZerosLoop:
1883             while (i < len) {
1884                 c = in.charAt(i);
1885                 if (c == '0') {
1886                     nLeadZero++;
1887                 } else if (c == '.') {
1888                     if (decSeen) {
1889                         // already saw one ., this is the 2nd.
1890                         throw new NumberFormatException("multiple points");
1891                     }
1892                     decPt = i;
1893                     if (signSeen) {
1894                         decPt -= 1;
1895                     }
1896                     decSeen = true;
1897                 } else {
1898                     break skipLeadingZerosLoop;
1899                 }
1900                 i++;


2120                 //
2121                 // There are a number of significand scenarios to consider;
2122                 // letters are used in indicate nonzero digits:
2123                 //
2124                 // 1. 000xxxx       =>      x.xxx   normalized
2125                 //    increase exponent by (number of x's - 1)*4
2126                 //
2127                 // 2. 000xxx.yyyy =>        x.xxyyyy        normalized
2128                 //    increase exponent by (number of x's - 1)*4
2129                 //
2130                 // 3. .000yyy  =>   y.yy    normalized
2131                 //    decrease exponent by (number of zeros + 1)*4
2132                 //
2133                 // 4. 000.00000yyy => y.yy normalized
2134                 //    decrease exponent by (number of zeros to right of point + 1)*4
2135                 //
2136                 // If the significand is exactly zero, return a properly
2137                 // signed zero.
2138                 //
2139 
2140                 String significandString;
2141                 int signifLength;
2142                 int exponentAdjust;
2143                 {
2144                     int leftDigits = 0; // number of meaningful digits to
2145                     // left of "decimal" point
2146                     // (leading zeros stripped)
2147                     int rightDigits = 0; // number of digits to right of
2148                     // "decimal" point; leading zeros
2149                     // must always be accounted for
2150                     //
2151                     // The significand is made up of either
2152                     //
2153                     // 1. group 4 entirely (integer portion only)
2154                     //
2155                     // OR
2156                     //
2157                     // 2. the fractional portion from group 7 plus any
2158                     // (optional) integer portions from group 6.
2159                     //
2160                     String group4;
2161                     if ((group4 = m.group(4)) != null) {  // Integer-only significand
2162                         // Leading zeros never matter on the integer portion


2229                     //              -       +0.0            -0.0
2230                     return isNegative ?
2231                               (positiveExponent ? A2BC_NEGATIVE_INFINITY : A2BC_NEGATIVE_ZERO)
2232                             : (positiveExponent ? A2BC_POSITIVE_INFINITY : A2BC_POSITIVE_ZERO);
2233 
2234                 }
2235 
2236                 long rawExponent =
2237                         (positiveExponent ? 1L : -1L) * // exponent sign
2238                                 unsignedRawExponent;            // exponent magnitude
2239 
2240                 // Calculate partially adjusted exponent
2241                 long exponent = rawExponent + exponentAdjust;
2242 
2243                 // Starting copying non-zero bits into proper position in
2244                 // a long; copy explicit bit too; this will be masked
2245                 // later for normal values.
2246 
2247                 boolean round = false;
2248                 boolean sticky = false;
2249                 int nextShift;
2250                 long significand = 0L;
2251                 // First iteration is different, since we only copy
2252                 // from the leading significand bit; one more exponent
2253                 // adjust will be needed...
2254 
2255                 // IMPORTANT: make leadingDigit a long to avoid
2256                 // surprising shift semantics!
2257                 long leadingDigit = getHexDigit(significandString, 0);
2258 
2259                 //
2260                 // Left shift the leading digit (53 - (bit position of
2261                 // leading 1 in digit)); this sets the top bit of the
2262                 // significand to 1.  The nextShift value is adjusted
2263                 // to take into account the number of bit positions of
2264                 // the leadingDigit actually used.  Finally, the
2265                 // exponent is adjusted to normalize the significand
2266                 // as a binary value, not just a hex value.
2267                 //
2268                 if (leadingDigit == 1) {
2269                     significand |= leadingDigit << 52;


2508                     //
2509                     boolean leastZero = ((significand & 1L) == 0L);
2510                     if ((leastZero && round && sticky) ||
2511                             ((!leastZero) && round)) {
2512                         significand++;
2513                     }
2514 
2515                     double value = isNegative ?
2516                             Double.longBitsToDouble(significand | DoubleConsts.SIGN_BIT_MASK) :
2517                             Double.longBitsToDouble(significand );
2518 
2519                     return new PreparedASCIIToBinaryBuffer(value, fValue);
2520                 }
2521             }
2522     }
2523 
2524     /**
2525      * Returns <code>s</code> with any leading zeros removed.
2526      */
2527     static String stripLeadingZeros(String s) {

2528         if(!s.isEmpty() && s.charAt(0)=='0') {
2529             for(int i=1; i<s.length(); i++) {
2530                 if(s.charAt(i)!='0') {
2531                     return s.substring(i);
2532                 }
2533             }
2534             return "";
2535         }
2536         return s;
2537     }
2538 
2539     /**
2540      * Extracts a hexadecimal digit from position <code>position</code>
2541      * of string <code>s</code>.
2542      */
2543     static int getHexDigit(String s, int position) {
2544         int value = Character.digit(s.charAt(position), 16);
2545         if (value <= -1 || value >= 16) {
2546             throw new AssertionError("Unexpected failure of digit conversion of " +
2547                                      s.charAt(position));
< prev index next >