# HG changeset patch # User lello # Date 1584472052 -3600 # Tue Mar 17 20:07:32 2020 +0100 # Node ID ec615c419ab236ae291651f5a810807f05fb4421 # Parent 42b62267498dbea03a82eeb073c6020b4b43d288 Patch to fix JDK-4511638 4511638: Double.toString(double) sometimes produces incorrect results Reviewed-by: TBD Contributed-by: Raffaello Giulietti diff --git a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java --- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java +++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java @@ -25,8 +25,10 @@ package java.lang; -import jdk.internal.math.FloatingDecimal; +import jdk.internal.math.DoubleToDecimal; +import jdk.internal.math.FloatToDecimal; +import java.io.IOException; import java.util.Arrays; import java.util.Spliterator; import java.util.stream.IntStream; @@ -880,7 +882,11 @@ * @return a reference to this object. */ public AbstractStringBuilder append(float f) { - FloatingDecimal.appendTo(f,this); + try { + FloatToDecimal.appendTo(f, this); + } catch (IOException ignored) { + assert false; + } return this; } @@ -897,7 +903,11 @@ * @return a reference to this object. */ public AbstractStringBuilder append(double d) { - FloatingDecimal.appendTo(d,this); + try { + DoubleToDecimal.appendTo(d, this); + } catch (IOException ignored) { + assert false; + } return this; } diff --git a/src/java.base/share/classes/java/lang/Double.java b/src/java.base/share/classes/java/lang/Double.java --- a/src/java.base/share/classes/java/lang/Double.java +++ b/src/java.base/share/classes/java/lang/Double.java @@ -32,6 +32,7 @@ import jdk.internal.math.FloatingDecimal; import jdk.internal.math.DoubleConsts; +import jdk.internal.math.DoubleToDecimal; import jdk.internal.HotSpotIntrinsicCandidate; /** @@ -145,69 +146,120 @@ public static final Class TYPE = (Class) Class.getPrimitiveClass("double"); /** - * Returns a string representation of the {@code double} - * argument. All characters mentioned below are ASCII characters. - *
- *
• If the argument is NaN, the result is the string - * "{@code NaN}". - *
• Otherwise, the result is a string that represents the sign and - * magnitude (absolute value) of the argument. If the sign is negative, - * the first character of the result is '{@code -}' - * ({@code '\u005Cu002D'}); if the sign is positive, no sign character - * appears in the result. As for the magnitude m: - *
- *
• If m is infinity, it is represented by the characters - * {@code "Infinity"}; thus, positive infinity produces the result - * {@code "Infinity"} and negative infinity produces the result - * {@code "-Infinity"}. - * - *
• If m is zero, it is represented by the characters - * {@code "0.0"}; thus, negative zero produces the result - * {@code "-0.0"} and positive zero produces the result - * {@code "0.0"}. + * Returns a string rendering of the {@code double} argument. * - *
• If m is greater than or equal to 10-3 but less - * than 107, then it is represented as the integer part of - * m, in decimal form with no leading zeroes, followed by - * '{@code .}' ({@code '\u005Cu002E'}), followed by one or - * more decimal digits representing the fractional part of m. - * - *
• If m is less than 10-3 or greater than or - * equal to 107, then it is represented in so-called - * "computerized scientific notation." Let n be the unique - * integer such that 10nm {@literal <} - * 10n+1; then let a be the - * mathematically exact quotient of m and - * 10n so that 1 ≤ a {@literal <} 10. The - * magnitude is then represented as the integer part of a, - * as a single decimal digit, followed by '{@code .}' - * ({@code '\u005Cu002E'}), followed by decimal digits - * representing the fractional part of a, followed by the - * letter '{@code E}' ({@code '\u005Cu0045'}), followed - * by a representation of n as a decimal integer, as - * produced by the method {@link Integer#toString(int)}. + *

The characters of the result are all drawn from the ASCII set. + *

+ *
• Any NaN, whether quiet or signaling, is rendered as + * {@code "NaN"}, regardless of the sign bit. + *
• The infinities +∞ and -∞ are rendered as + * {@code "Infinity"} and {@code "-Infinity"}, respectively. + *
• The positive and negative zeroes are rendered as + * {@code "0.0"} and {@code "-0.0"}, respectively. + *
• A finite negative {@code v} is rendered as the sign + * '{@code -}' followed by the rendering of the magnitude -{@code v}. + *
• A finite positive {@code v} is rendered in two stages: + *
+ *
• Selection of a decimal: A well-defined + * decimal dv is selected + * to represent {@code v}. + *
• Formatting as a string: The decimal + * dv is formatted as a string, + * either in plain or in computerized scientific notation, + * depending on its value. *
*
- * How many digits must be printed for the fractional part of - * m or a? There must be at least one digit to represent - * the fractional part, and beyond that as many, but only as many, more - * digits as are needed to uniquely distinguish the argument value from - * adjacent values of type {@code double}. That is, suppose that - * x is the exact mathematical value represented by the decimal - * representation produced by this method for a finite nonzero argument - * d. Then d must be the {@code double} value nearest - * to x; or if two {@code double} values are equally close - * to x, then d must be one of them and the least - * significant bit of the significand of d must be {@code 0}. + * + *

A decimal is a number of the form + * d×10i + * for some (unique) integers d > 0 and i such that + * d is not a multiple of 10. + * These integers are the significand and + * the exponent, respectively, of the decimal. + * The length of the decimal is the (unique) + * integer n meeting + * 10n-1d < 10n. + * + *

The decimal dv + * for a finite positive {@code v} is defined as follows: + *

+ *
• Let R be the set of all decimals that round to {@code v} + * according to the usual round-to-closest rule of + * IEEE 754 floating-point arithmetic. + *
• Let m be the minimal length over all decimals in R. + *
• When m ≥ 2, let T be the set of all decimals + * in R with length m. + * Otherwise, let T be the set of all decimals + * in R with length 1 or 2. + *
• Define dv as + * the decimal in T that is closest to {@code v}. + * Or if there are two such decimals in T, + * select the one with the even significand (there is exactly one). + *
+ * + *

The (uniquely) selected decimal dv + * is then formatted. * - *

To create localized string representations of a floating-point - * value, use subclasses of {@link java.text.NumberFormat}. + *

Let d, i and n be the significand, exponent and + * length of dv, respectively. + * Further, let e = n + i - 1 and let + * d1dn + * be the usual decimal expansion of the significand. + * Note that d1 ≠ 0 ≠ dn. + *

+ *
• Case -3 ≤ e < 0: + * dv is formatted as + * 0.00d1dn, + * where there are exactly -(n + i) zeroes between + * the decimal point and d1. + * For example, 123 × 10-4 is formatted as + * {@code 0.0123}. + *
• Case 0 ≤ e < 7: + *
+ *
• Subcase i ≥ 0: + * dv is formatted as + * d1dn00.0, + * where there are exactly i zeroes + * between dn and the decimal point. + * For example, 123 × 102 is formatted as + * {@code 12300.0}. + *
• Subcase i < 0: + * dv is formatted as + * d1dn+i.dn+i+1dn. + * There are exactly -i digits to the right of + * the decimal point. + * For example, 123 × 10-1 is formatted as + * {@code 12.3}. + *
+ *
• Case e < -3 or e ≥ 7: + * computerized scientific notation is used to format + * dv. + * Here e is formatted as by {@link Integer#toString(int)}. + *
+ *
• Subcase n = 1: + * dv is formatted as + * d1.0Ee. + * For example, 1 × 1023 is formatted as + * {@code 1.0E23}. + *
• Subcase n > 1: + * dv is formatted as + * d1.d2dnEe. + * For example, 123 × 10-21 is formatted as + * {@code 1.23E-19}. + *
+ *
* - * @param d the {@code double} to be converted. - * @return a string representation of the argument. + * @param v the {@code double} to be rendered. + * @return a string rendering of the argument. */ - public static String toString(double d) { - return FloatingDecimal.toJavaFormatString(d); + public static String toString(double v) { + return DoubleToDecimal.toString(v); } /** diff --git a/src/java.base/share/classes/java/lang/Float.java b/src/java.base/share/classes/java/lang/Float.java --- a/src/java.base/share/classes/java/lang/Float.java +++ b/src/java.base/share/classes/java/lang/Float.java @@ -31,6 +31,7 @@ import java.util.Optional; import jdk.internal.math.FloatingDecimal; +import jdk.internal.math.FloatToDecimal; import jdk.internal.HotSpotIntrinsicCandidate; /** @@ -142,73 +143,120 @@ public static final Class TYPE = (Class) Class.getPrimitiveClass("float"); /** - * Returns a string representation of the {@code float} - * argument. All characters mentioned below are ASCII characters. - *
- *
• If the argument is NaN, the result is the string - * "{@code NaN}". - *
• Otherwise, the result is a string that represents the sign and - * magnitude (absolute value) of the argument. If the sign is - * negative, the first character of the result is - * '{@code -}' ({@code '\u005Cu002D'}); if the sign is - * positive, no sign character appears in the result. As for - * the magnitude m: + * Returns a string rendering of the {@code float} argument. + * + *

The characters of the result are all drawn from the ASCII set. *

- *
• If m is infinity, it is represented by the characters - * {@code "Infinity"}; thus, positive infinity produces - * the result {@code "Infinity"} and negative infinity - * produces the result {@code "-Infinity"}. - *
• If m is zero, it is represented by the characters - * {@code "0.0"}; thus, negative zero produces the result - * {@code "-0.0"} and positive zero produces the result - * {@code "0.0"}. - *
• If m is greater than or equal to 10-3 but - * less than 107, then it is represented as the - * integer part of m, in decimal form with no leading - * zeroes, followed by '{@code .}' - * ({@code '\u005Cu002E'}), followed by one or more - * decimal digits representing the fractional part of - * m. - *
• If m is less than 10-3 or greater than or - * equal to 107, then it is represented in - * so-called "computerized scientific notation." Let n - * be the unique integer such that 10n ≤ - * m {@literal <} 10n+1; then let a - * be the mathematically exact quotient of m and - * 10n so that 1 ≤ a {@literal <} 10. - * The magnitude is then represented as the integer part of - * a, as a single decimal digit, followed by - * '{@code .}' ({@code '\u005Cu002E'}), followed by - * decimal digits representing the fractional part of - * a, followed by the letter '{@code E}' - * ({@code '\u005Cu0045'}), followed by a representation - * of n as a decimal integer, as produced by the - * method {@link java.lang.Integer#toString(int)}. - * + *
• Any NaN, whether quiet or signaling, is rendered as + * {@code "NaN"}, regardless of the sign bit. + *
• The infinities +∞ and -∞ are rendered as + * {@code "Infinity"} and {@code "-Infinity"}, respectively. + *
• The positive and negative zeroes are rendered as + * {@code "0.0"} and {@code "-0.0"}, respectively. + *
• A finite negative {@code v} is rendered as the sign + * '{@code -}' followed by the rendering of the magnitude -{@code v}. + *
• A finite positive {@code v} is rendered in two stages: + *
+ *
• Selection of a decimal: A well-defined + * decimal dv is selected + * to represent {@code v}. + *
• Formatting as a string: The decimal + * dv is formatted as a string, + * either in plain or in computerized scientific notation, + * depending on its value. *
*
- * How many digits must be printed for the fractional part of - * m or a? There must be at least one digit - * to represent the fractional part, and beyond that as many, but - * only as many, more digits as are needed to uniquely distinguish - * the argument value from adjacent values of type - * {@code float}. That is, suppose that x is the - * exact mathematical value represented by the decimal - * representation produced by this method for a finite nonzero - * argument f. Then f must be the {@code float} - * value nearest to x; or, if two {@code float} values are - * equally close to x, then f must be one of - * them and the least significant bit of the significand of - * f must be {@code 0}. + * + *

A decimal is a number of the form + * d×10i + * for some (unique) integers d > 0 and i such that + * d is not a multiple of 10. + * These integers are the significand and + * the exponent, respectively, of the decimal. + * The length of the decimal is the (unique) + * integer n meeting + * 10n-1d < 10n. + * + *

The decimal dv + * for a finite positive {@code v} is defined as follows: + *

+ *
• Let R be the set of all decimals that round to {@code v} + * according to the usual round-to-closest rule of + * IEEE 754 floating-point arithmetic. + *
• Let m be the minimal length over all decimals in R. + *
• When m ≥ 2, let T be the set of all decimals + * in R with length m. + * Otherwise, let T be the set of all decimals + * in R with length 1 or 2. + *
• Define dv as + * the decimal in T that is closest to {@code v}. + * Or if there are two such decimals in T, + * select the one with the even significand (there is exactly one). + *
+ * + *

The (uniquely) selected decimal dv + * is then formatted. * - *

To create localized string representations of a floating-point - * value, use subclasses of {@link java.text.NumberFormat}. + *

Let d, i and n be the significand, exponent and + * length of dv, respectively. + * Further, let e = n + i - 1 and let + * d1dn + * be the usual decimal expansion of the significand. + * Note that d1 ≠ 0 ≠ dn. + *

+ *
• Case -3 ≤ e < 0: + * dv is formatted as + * 0.00d1dn, + * where there are exactly -(n + i) zeroes between + * the decimal point and d1. + * For example, 123 × 10-4 is formatted as + * {@code 0.0123}. + *
• Case 0 ≤ e < 7: + *
+ *
• Subcase i ≥ 0: + * dv is formatted as + * d1dn00.0, + * where there are exactly i zeroes + * between dn and the decimal point. + * For example, 123 × 102 is formatted as + * {@code 12300.0}. + *
• Subcase i < 0: + * dv is formatted as + * d1dn+i.dn+i+1dn. + * There are exactly -i digits to the right of + * the decimal point. + * For example, 123 × 10-1 is formatted as + * {@code 12.3}. + *
+ *
• Case e < -3 or e ≥ 7: + * computerized scientific notation is used to format + * dv. + * Here e is formatted as by {@link Integer#toString(int)}. + *
+ *
• Subcase n = 1: + * dv is formatted as + * d1.0Ee. + * For example, 1 × 1023 is formatted as + * {@code 1.0E23}. + *
• Subcase n > 1: + * dv is formatted as + * d1.d2dnEe. + * For example, 123 × 10-21 is formatted as + * {@code 1.23E-19}. + *
+ *
* - * @param f the float to be converted. - * @return a string representation of the argument. + * @param v the {@code float} to be rendered. + * @return a string rendering of the argument. */ - public static String toString(float f) { - return FloatingDecimal.toJavaFormatString(f); + public static String toString(float v) { + return FloatToDecimal.toString(v); } /** diff --git a/src/java.base/share/classes/jdk/internal/math/DoubleToDecimal.java b/src/java.base/share/classes/jdk/internal/math/DoubleToDecimal.java new file mode 100644 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/math/DoubleToDecimal.java @@ -0,0 +1,644 @@ +/* + * Copyright 2018-2020 Raffaello Giulietti + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package jdk.internal.math; + +import java.io.IOException; + +import static java.lang.Double.*; +import static java.lang.Long.*; +import static java.lang.Math.multiplyHigh; +import static jdk.internal.math.MathUtils.*; + +/** + * This class exposes a method to render a {@code double} as a string. + * + * @author Raffaello Giulietti + */ +final public class DoubleToDecimal { + /* + For full details about this code see the following references: + + [1] Giulietti, "The Schubfach way to render doubles", + https://drive.google.com/open?id=1luHhyQF9zKlM8yJ1nebU0OgVYhfC6CBN + + [2] IEEE Computer Society, "IEEE Standard for Floating-Point Arithmetic" + + [3] Bouvier & Zimmermann, "Division-Free Binary-to-Decimal Conversion" + + Divisions are avoided altogether for the benefit of those architectures + that do not provide specific machine instructions or where they are slow. + This is discussed in section 10 of [1]. + */ + + // The precision in bits. + static final int P = 53; + + // Exponent width in bits. + private static final int W = (Double.SIZE - 1) - (P - 1); + + // Minimum value of the exponent: -(2^(W-1)) - P + 3. + static final int Q_MIN = (-1 << W - 1) - P + 3; + + // Maximum value of the exponent: 2^(W-1) - P. + static final int Q_MAX = (1 << W - 1) - P; + + // 10^(E_MIN - 1) <= MIN_VALUE < 10^E_MIN + static final int E_MIN = -323; + + // 10^(E_MAX - 1) <= MAX_VALUE < 10^E_MAX + static final int E_MAX = 309; + + // Threshold to detect tiny values, as in section 8.1.1 of [1] + static final long C_TINY = 3; + + // The minimum and maximum k, as in section 8 of [1] + static final int K_MIN = -324; + static final int K_MAX = 292; + + // H is as in section 8 of [1]. + static final int H = 17; + + // Minimum value of the significand of a normal value: 2^(P-1). + private static final long C_MIN = 1L << P - 1; + + // Mask to extract the biased exponent. + private static final int BQ_MASK = (1 << W) - 1; + + // Mask to extract the fraction bits. + private static final long T_MASK = (1L << P - 1) - 1; + + // Used in rop(). + private static final long MASK_63 = (1L << 63) - 1; + + // Used for left-to-tight digit extraction. + private static final int MASK_28 = (1 << 28) - 1; + + private static final int NON_SPECIAL = 0; + private static final int PLUS_ZERO = 1; + private static final int MINUS_ZERO = 2; + private static final int PLUS_INF = 3; + private static final int MINUS_INF = 4; + private static final int NAN = 5; + + // For thread-safety, each thread gets its own instance of this class. + private static final ThreadLocal threadLocal = + ThreadLocal.withInitial(DoubleToDecimal::new); + + /* + Room for the longer of the forms + -ddddd.dddddddddddd H + 2 characters + -0.00ddddddddddddddddd H + 5 characters + -d.ddddddddddddddddE-eee H + 7 characters + where there are H digits d + */ + public final int MAX_CHARS = H + 7; + + // Numerical results are created here... + private final byte[] bytes = new byte[MAX_CHARS]; + + // ... and copied here in appendTo() + private final char[] chars = new char[MAX_CHARS]; + + // Index into bytes of rightmost valid character. + private int index; + + private DoubleToDecimal() { + } + + /** + * Returns a string rendering of the {@code double} argument. + * + *

The characters of the result are all drawn from the ASCII set. + *

+ *
• Any NaN, whether quiet or signaling, is rendered as + * {@code "NaN"}, regardless of the sign bit. + *
• The infinities +∞ and -∞ are rendered as + * {@code "Infinity"} and {@code "-Infinity"}, respectively. + *
• The positive and negative zeroes are rendered as + * {@code "0.0"} and {@code "-0.0"}, respectively. + *
• A finite negative {@code v} is rendered as the sign + * '{@code -}' followed by the rendering of the magnitude -{@code v}. + *
• A finite positive {@code v} is rendered in two stages: + *
+ *
• Selection of a decimal: A well-defined + * decimal dv is selected + * to represent {@code v}. + *
• Formatting as a string: The decimal + * dv is formatted as a string, + * either in plain or in computerized scientific notation, + * depending on its value. + *
+ *
+ * + *

A decimal is a number of the form + * d×10i + * for some (unique) integers d > 0 and i such that + * d is not a multiple of 10. + * These integers are the significand and + * the exponent, respectively, of the decimal. + * The length of the decimal is the (unique) + * integer n meeting + * 10n-1d < 10n. + * + *

The decimal dv + * for a finite positive {@code v} is defined as follows: + *

+ *
• Let R be the set of all decimals that round to {@code v} + * according to the usual round-to-closest rule of + * IEEE 754 floating-point arithmetic. + *
• Let m be the minimal length over all decimals in R. + *
• When m ≥ 2, let T be the set of all decimals + * in R with length m. + * Otherwise, let T be the set of all decimals + * in R with length 1 or 2. + *
• Define dv as + * the decimal in T that is closest to {@code v}. + * Or if there are two such decimals in T, + * select the one with the even significand (there is exactly one). + *
+ * + *

The (uniquely) selected decimal dv + * is then formatted. + * + *

Let d, i and n be the significand, exponent and + * length of dv, respectively. + * Further, let e = n + i - 1 and let + * d1dn + * be the usual decimal expansion of the significand. + * Note that d1 ≠ 0 ≠ dn. + *

+ *
• Case -3 ≤ e < 0: + * dv is formatted as + * 0.00d1dn, + * where there are exactly -(n + i) zeroes between + * the decimal point and d1. + * For example, 123 × 10-4 is formatted as + * {@code 0.0123}. + *
• Case 0 ≤ e < 7: + *
+ *
• Subcase i ≥ 0: + * dv is formatted as + * d1dn00.0, + * where there are exactly i zeroes + * between dn and the decimal point. + * For example, 123 × 102 is formatted as + * {@code 12300.0}. + *
• Subcase i < 0: + * dv is formatted as + * d1dn+i.dn+i+1dn. + * There are exactly -i digits to the right of + * the decimal point. + * For example, 123 × 10-1 is formatted as + * {@code 12.3}. + *
+ *
• Case e < -3 or e ≥ 7: + * computerized scientific notation is used to format + * dv. + * Here e is formatted as by {@link Integer#toString(int)}. + *
+ *
• Subcase n = 1: + * dv is formatted as + * d1.0Ee. + * For example, 1 × 1023 is formatted as + * {@code 1.0E23}. + *
• Subcase n > 1: + * dv is formatted as + * d1.d2dnEe. + * For example, 123 × 10-21 is formatted as + * {@code 1.23E-19}. + *
+ *
+ * + * @param v the {@code double} to be rendered. + * @return a string rendering of the argument. + */ + public static String toString(double v) { + return threadLocalInstance().toDecimalString(v); + } + + /** + * Appends the rendering of the {@code v} to {@code app}. + * + *

The characters of the result are all drawn from the ASCII set. + *

+ *
• Any NaN, whether quiet or signaling, is rendered as + * {@code "NaN"}, regardless of the sign bit. + *
• The infinities +∞ and -∞ are rendered as + * {@code "Infinity"} and {@code "-Infinity"}, respectively. + *
• The positive and negative zeroes are rendered as + * {@code "0.0"} and {@code "-0.0"}, respectively. + *
• A finite negative {@code v} is rendered as the sign + * '{@code -}' followed by the rendering of the magnitude -{@code v}. + *
• A finite positive {@code v} is rendered in two stages: + *
+ *
• Selection of a decimal: A well-defined + * decimal dv is selected + * to represent {@code v}. + *
• Formatting as a string: The decimal + * dv is formatted as a string, + * either in plain or in computerized scientific notation, + * depending on its value. + *
+ *
+ * + *

A decimal is a number of the form + * d×10i + * for some (unique) integers d > 0 and i such that + * d is not a multiple of 10. + * These integers are the significand and + * the exponent, respectively, of the decimal. + * The length of the decimal is the (unique) + * integer n meeting + * 10n-1d < 10n. + * + *

The decimal dv + * for a finite positive {@code v} is defined as follows: + *

+ *
• Let R be the set of all decimals that round to {@code v} + * according to the usual round-to-closest rule of + * IEEE 754 floating-point arithmetic. + *
• Let m be the minimal length over all decimals in R. + *
• When m ≥ 2, let T be the set of all decimals + * in R with length m. + * Otherwise, let T be the set of all decimals + * in R with length 1 or 2. + *
• Define dv as + * the decimal in T that is closest to {@code v}. + * Or if there are two such decimals in T, + * select the one with the even significand (there is exactly one). + *
+ * + *

The (uniquely) selected decimal dv + * is then formatted. + * + *

Let d, i and n be the significand, exponent and + * length of dv, respectively. + * Further, let e = n + i - 1 and let + * d1dn + * be the usual decimal expansion of the significand. + * Note that d1 ≠ 0 ≠ dn. + *

+ *
• Case -3 ≤ e < 0: + * dv is formatted as + * 0.00d1dn, + * where there are exactly -(n + i) zeroes between + * the decimal point and d1. + * For example, 123 × 10-4 is formatted as + * {@code 0.0123}. + *
• Case 0 ≤ e < 7: + *
+ *
• Subcase i ≥ 0: + * dv is formatted as + * d1dn00.0, + * where there are exactly i zeroes + * between dn and the decimal point. + * For example, 123 × 102 is formatted as + * {@code 12300.0}. + *
• Subcase i < 0: + * dv is formatted as + * d1dn+i.dn+i+1dn. + * There are exactly -i digits to the right of + * the decimal point. + * For example, 123 × 10-1 is formatted as + * {@code 12.3}. + *
+ *
• Case e < -3 or e ≥ 7: + * computerized scientific notation is used to format + * dv. + * Here e is formatted as by {@link Integer#toString(int)}. + *
+ *
• Subcase n = 1: + * dv is formatted as + * d1.0Ee. + * For example, 1 × 1023 is formatted as + * {@code 1.0E23}. + *
• Subcase n > 1: + * dv is formatted as + * d1.d2dnEe. + * For example, 123 × 10-21 is formatted as + * {@code 1.23E-19}. + *
+ *
+ * + * @param v the {@code float} to be rendered. + * @return a string rendering of the argument. + */ + public static String toString(float v) { + return threadLocalInstance().toDecimalString(v); + } + + /** + * Appends the rendering of the {@code v} to {@code app}. + * + *