Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
cc10a92
4511638: Double.toString(double) sometimes produces incorrect results
rgiulietti Apr 8, 2021
22092f0
4511638: Double.toString(double) sometimes produces incorrect results
rgiulietti Apr 16, 2021
24bae6a
Changed MAX_CHARS to static
rgiulietti Apr 22, 2021
e54c1ea
4511638: Double.toString(double) sometimes produces incorrect results
rgiulietti Oct 20, 2021
75b2a3f
4511638: Double.toString(double) sometimes produces incorrect results
rgiulietti Oct 20, 2021
1fbd931
4511638: Double.toString(double) sometimes produces incorrect results
rgiulietti Oct 20, 2021
82c359a
4511638: Double.toString(double) sometimes produces incorrect results
rgiulietti Oct 21, 2021
2d669fc
4511638: Double.toString(double) sometimes produces incorrect results
rgiulietti Oct 27, 2021
37acd52
4511638: Double.toString(double) sometimes produces incorrect results
rgiulietti Oct 27, 2021
45881cd
4511638: Double.toString(double) sometimes produces incorrect results
rgiulietti Nov 15, 2021
7ca049a
4511638: Double.toString(double) sometimes produces incorrect results
rgiulietti Feb 8, 2022
c29dff7
4511638: Double.toString(double) sometimes produces incorrect results
rgiulietti Feb 8, 2022
a36ff8a
4511638: Double.toString(double) sometimes produces incorrect results
rgiulietti May 6, 2022
904ba11
4511638: Double.toString(double) sometimes produces incorrect results
rgiulietti May 6, 2022
e7c4bd2
4511638: Double.toString(double) sometimes produces incorrect results
rgiulietti May 6, 2022
bd323d1
4511638: Double.toString(double) sometimes produces incorrect results
rgiulietti May 9, 2022
907abfd
4511638: Double.toString(double) sometimes produces incorrect results
rgiulietti May 9, 2022
b40d7e8
4511638: Double.toString(double) sometimes produces incorrect results
rgiulietti May 11, 2022
31ca4e1
4511638: Double.toString(double) sometimes produces incorrect results
rgiulietti May 13, 2022
ad146ec
4511638: Double.toString(double) sometimes produces incorrect results
rgiulietti May 31, 2022
93711ba
4511638: Double.toString(double) sometimes produces incorrect results
rgiulietti Jun 1, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions src/java.base/share/classes/java/lang/AbstractStringBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -875,8 +877,13 @@ public AbstractStringBuilder append(long l) {
* @return a reference to this object.
*/
public AbstractStringBuilder append(float f) {
FloatingDecimal.appendTo(f,this);
try {
FloatToDecimal.appendTo(f, this);
} catch (IOException e) {
throw new AssertionError(e);
}
return this;

}

/**
Expand All @@ -892,7 +899,11 @@ public AbstractStringBuilder append(float f) {
* @return a reference to this object.
*/
public AbstractStringBuilder append(double d) {
FloatingDecimal.appendTo(d,this);
try {
DoubleToDecimal.appendTo(d, this);
} catch (IOException e) {
throw new AssertionError(e);
}
return this;
}

Expand Down
135 changes: 103 additions & 32 deletions src/java.base/share/classes/java/lang/Double.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

import jdk.internal.math.FloatingDecimal;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Presumably the FloatingDecimal import here and in Float can be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FloatingDecimal is used in the parse*(String) methods

import jdk.internal.math.DoubleConsts;
import jdk.internal.math.DoubleToDecimal;
import jdk.internal.vm.annotation.IntrinsicCandidate;

/**
Expand Down Expand Up @@ -280,39 +281,109 @@ public final class Double extends Number
* {@code "-0.0"} and positive zero produces the result
* {@code "0.0"}.
*
* <li>If <i>m</i> is greater than or equal to 10<sup>-3</sup> but less
* than 10<sup>7</sup>, then it is represented as the integer part of
* <i>m</i>, in decimal form with no leading zeroes, followed by
* '{@code .}' ({@code '\u005Cu002E'}), followed by one or
* more decimal digits representing the fractional part of <i>m</i>.
*
* <li>If <i>m</i> is less than 10<sup>-3</sup> or greater than or
* equal to 10<sup>7</sup>, then it is represented in so-called
* "computerized scientific notation." Let <i>n</i> be the unique
* integer such that 10<sup><i>n</i></sup> &le; <i>m</i> {@literal <}
* 10<sup><i>n</i>+1</sup>; then let <i>a</i> be the
* mathematically exact quotient of <i>m</i> and
* 10<sup><i>n</i></sup> so that 1 &le; <i>a</i> {@literal <} 10. The
* magnitude is then represented as the integer part of <i>a</i>,
* as a single decimal digit, followed by '{@code .}'
* ({@code '\u005Cu002E'}), followed by decimal digits
* representing the fractional part of <i>a</i>, followed by the
* letter '{@code E}' ({@code '\u005Cu0045'}), followed
* by a representation of <i>n</i> as a decimal integer, as
* produced by the method {@link Integer#toString(int)}.
* <li> Otherwise <i>m</i> is positive and finite.
* It is converted to a string in two stages:
* <ul>
* <li> <em>Selection of a decimal</em>:
* A well-defined decimal <i>d</i><sub><i>m</i></sub>
* is selected to represent <i>m</i>.
* This decimal is (almost always) the <em>shortest</em> one that
* rounds to <i>m</i> according to the round to nearest
* rounding policy of IEEE 754 floating-point arithmetic.
* <li> <em>Formatting as a string</em>:
* The decimal <i>d</i><sub><i>m</i></sub> is formatted as a string,
* either in plain or in computerized scientific notation,
* depending on its value.
* </ul>
* </ul>
* </ul>
*
* <p>A <em>decimal</em> is a number of the form
* <i>s</i>&times;10<sup><i>i</i></sup>
* for some (unique) integers <i>s</i> &gt; 0 and <i>i</i> such that
* <i>s</i> is not a multiple of 10.
* These integers are the <em>significand</em> and
* the <em>exponent</em>, respectively, of the decimal.
* The <em>length</em> of the decimal is the (unique)
* positive integer <i>n</i> meeting
* 10<sup><i>n</i>-1</sup> &le; <i>s</i> &lt; 10<sup><i>n</i></sup>.
*
* <p>The decimal <i>d</i><sub><i>m</i></sub> for a finite positive <i>m</i>
* is defined as follows:
* <ul>
* <li>Let <i>R</i> be the set of all decimals that round to <i>m</i>
* according to the usual <em>round to nearest</em> rounding policy of
* IEEE 754 floating-point arithmetic.
* <li>Let <i>p</i> be the minimal length over all decimals in <i>R</i>.
* <li>When <i>p</i> &ge; 2, let <i>T</i> be the set of all decimals
* in <i>R</i> with length <i>p</i>.
* Otherwise, let <i>T</i> be the set of all decimals
* in <i>R</i> with length 1 or 2.
* <li>Define <i>d</i><sub><i>m</i></sub> as the decimal in <i>T</i>
* that is closest to <i>m</i>.
* Or if there are two such decimals in <i>T</i>,
* select the one with the even significand.
* </ul>
*
* <p>The (uniquely) selected decimal <i>d</i><sub><i>m</i></sub>
* is then formatted.
* Let <i>s</i>, <i>i</i> and <i>n</i> be the significand, exponent and
* length of <i>d</i><sub><i>m</i></sub>, respectively.
* Further, let <i>e</i> = <i>n</i> + <i>i</i> - 1 and let
* <i>s</i><sub>1</sub>&hellip;<i>s</i><sub><i>n</i></sub>
* be the usual decimal expansion of <i>s</i>.
* Note that <i>s</i><sub>1</sub> &ne; 0
* and <i>s</i><sub><i>n</i></sub> &ne; 0.
* Below, the decimal point {@code '.'} is {@code '\u005Cu002E'}
* and the exponent indicator {@code 'E'} is {@code '\u005Cu0045'}.
* <ul>
* <li>Case -3 &le; <i>e</i> &lt; 0:
* <i>d</i><sub><i>m</i></sub> is formatted as
* <code>0.0</code>&hellip;<code>0</code><!--
* --><i>s</i><sub>1</sub>&hellip;<i>s</i><sub><i>n</i></sub>,
* where there are exactly -(<i>n</i> + <i>i</i>) zeroes between
* the decimal point and <i>s</i><sub>1</sub>.
* For example, 123 &times; 10<sup>-4</sup> is formatted as
* {@code 0.0123}.
* <li>Case 0 &le; <i>e</i> &lt; 7:
* <ul>
* <li>Subcase <i>i</i> &ge; 0:
* <i>d</i><sub><i>m</i></sub> is formatted as
* <i>s</i><sub>1</sub>&hellip;<i>s</i><sub><i>n</i></sub><!--
* --><code>0</code>&hellip;<code>0.0</code>,
* where there are exactly <i>i</i> zeroes
* between <i>s</i><sub><i>n</i></sub> and the decimal point.
* For example, 123 &times; 10<sup>2</sup> is formatted as
* {@code 12300.0}.
* <li>Subcase <i>i</i> &lt; 0:
* <i>d</i><sub><i>m</i></sub> is formatted as
* <i>s</i><sub>1</sub>&hellip;<!--
* --><i>s</i><sub><i>n</i>+<i>i</i></sub><code>.</code><!--
* --><i>s</i><sub><i>n</i>+<i>i</i>+1</sub>&hellip;<!--
* --><i>s</i><sub><i>n</i></sub>,
* where there are exactly -<i>i</i> digits to the right of
* the decimal point.
* For example, 123 &times; 10<sup>-1</sup> is formatted as
* {@code 12.3}.
* </ul>
* <li>Case <i>e</i> &lt; -3 or <i>e</i> &ge; 7:
* computerized scientific notation is used to format
* <i>d</i><sub><i>m</i></sub>.
* Here <i>e</i> is formatted as by {@link Integer#toString(int)}.
* <ul>
* <li>Subcase <i>n</i> = 1:
* <i>d</i><sub><i>m</i></sub> is formatted as
* <i>s</i><sub>1</sub><code>.0E</code><i>e</i>.
* For example, 1 &times; 10<sup>23</sup> is formatted as
* {@code 1.0E23}.
* <li>Subcase <i>n</i> &gt; 1:
* <i>d</i><sub><i>m</i></sub> is formatted as
* <i>s</i><sub>1</sub><code>.</code><i>s</i><sub>2</sub><!--
* -->&hellip;<i>s</i><sub><i>n</i></sub><code>E</code><i>e</i>.
* For example, 123 &times; 10<sup>-21</sup> is formatted as
* {@code 1.23E-19}.
* </ul>
* </ul>
* How many digits must be printed for the fractional part of
* <i>m</i> or <i>a</i>? 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
* <i>x</i> is the exact mathematical value represented by the decimal
* representation produced by this method for a finite nonzero argument
* <i>d</i>. Then <i>d</i> must be the {@code double} value nearest
* to <i>x</i>; or if two {@code double} values are equally close
* to <i>x</i>, then <i>d</i> must be one of them and the least
* significant bit of the significand of <i>d</i> must be {@code 0}.
*
* <p>To create localized string representations of a floating-point
* value, use subclasses of {@link java.text.NumberFormat}.
Expand All @@ -321,7 +392,7 @@ public final class Double extends Number
* @return a string representation of the argument.
*/
public static String toString(double d) {
return FloatingDecimal.toJavaFormatString(d);
return DoubleToDecimal.toString(d);
}

/**
Expand Down
141 changes: 104 additions & 37 deletions src/java.base/share/classes/java/lang/Float.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.util.Optional;

import jdk.internal.math.FloatingDecimal;
import jdk.internal.math.FloatToDecimal;
import jdk.internal.vm.annotation.IntrinsicCandidate;

/**
Expand Down Expand Up @@ -189,53 +190,119 @@ public final class Float extends Number
* {@code "0.0"}; thus, negative zero produces the result
* {@code "-0.0"} and positive zero produces the result
* {@code "0.0"}.
* <li> If <i>m</i> is greater than or equal to 10<sup>-3</sup> but
* less than 10<sup>7</sup>, then it is represented as the
* integer part of <i>m</i>, in decimal form with no leading
* zeroes, followed by '{@code .}'
* ({@code '\u005Cu002E'}), followed by one or more
* decimal digits representing the fractional part of
* <i>m</i>.
* <li> If <i>m</i> is less than 10<sup>-3</sup> or greater than or
* equal to 10<sup>7</sup>, then it is represented in
* so-called "computerized scientific notation." Let <i>n</i>
* be the unique integer such that 10<sup><i>n</i> </sup>&le;
* <i>m</i> {@literal <} 10<sup><i>n</i>+1</sup>; then let <i>a</i>
* be the mathematically exact quotient of <i>m</i> and
* 10<sup><i>n</i></sup> so that 1 &le; <i>a</i> {@literal <} 10.
* The magnitude is then represented as the integer part of
* <i>a</i>, as a single decimal digit, followed by
* '{@code .}' ({@code '\u005Cu002E'}), followed by
* decimal digits representing the fractional part of
* <i>a</i>, followed by the letter '{@code E}'
* ({@code '\u005Cu0045'}), followed by a representation
* of <i>n</i> as a decimal integer, as produced by the
* method {@link java.lang.Integer#toString(int)}.
*
* <li> Otherwise <i>m</i> is positive and finite.
* It is converted to a string in two stages:
* <ul>
* <li> <em>Selection of a decimal</em>:
* A well-defined decimal <i>d</i><sub><i>m</i></sub>
* is selected to represent <i>m</i>.
* This decimal is (almost always) the <em>shortest</em> one that
* rounds to <i>m</i> according to the round to nearest
* rounding policy of IEEE 754 floating-point arithmetic.
* <li> <em>Formatting as a string</em>:
* The decimal <i>d</i><sub><i>m</i></sub> is formatted as a string,
* either in plain or in computerized scientific notation,
* depending on its value.
* </ul>
* </ul>
* </ul>
*
* <p>A <em>decimal</em> is a number of the form
* <i>s</i>&times;10<sup><i>i</i></sup>
* for some (unique) integers <i>s</i> &gt; 0 and <i>i</i> such that
* <i>s</i> is not a multiple of 10.
* These integers are the <em>significand</em> and
* the <em>exponent</em>, respectively, of the decimal.
* The <em>length</em> of the decimal is the (unique)
* positive integer <i>n</i> meeting
* 10<sup><i>n</i>-1</sup> &le; <i>s</i> &lt; 10<sup><i>n</i></sup>.
*
* <p>The decimal <i>d</i><sub><i>m</i></sub> for a finite positive <i>m</i>
* is defined as follows:
* <ul>
* <li>Let <i>R</i> be the set of all decimals that round to <i>m</i>
* according to the usual <em>round to nearest</em> rounding policy of
* IEEE 754 floating-point arithmetic.
* <li>Let <i>p</i> be the minimal length over all decimals in <i>R</i>.
* <li>When <i>p</i> &ge; 2, let <i>T</i> be the set of all decimals
* in <i>R</i> with length <i>p</i>.
* Otherwise, let <i>T</i> be the set of all decimals
* in <i>R</i> with length 1 or 2.
* <li>Define <i>d</i><sub><i>m</i></sub> as the decimal in <i>T</i>
* that is closest to <i>m</i>.
* Or if there are two such decimals in <i>T</i>,
* select the one with the even significand.
* </ul>
*
* <p>The (uniquely) selected decimal <i>d</i><sub><i>m</i></sub>
* is then formatted.
* Let <i>s</i>, <i>i</i> and <i>n</i> be the significand, exponent and
* length of <i>d</i><sub><i>m</i></sub>, respectively.
* Further, let <i>e</i> = <i>n</i> + <i>i</i> - 1 and let
* <i>s</i><sub>1</sub>&hellip;<i>s</i><sub><i>n</i></sub>
* be the usual decimal expansion of <i>s</i>.
* Note that <i>s</i><sub>1</sub> &ne; 0
* and <i>s</i><sub><i>n</i></sub> &ne; 0.
* Below, the decimal point {@code '.'} is {@code '\u005Cu002E'}
* and the exponent indicator {@code 'E'} is {@code '\u005Cu0045'}.
* <ul>
* <li>Case -3 &le; <i>e</i> &lt; 0:
* <i>d</i><sub><i>m</i></sub> is formatted as
* <code>0.0</code>&hellip;<code>0</code><!--
* --><i>s</i><sub>1</sub>&hellip;<i>s</i><sub><i>n</i></sub>,
* where there are exactly -(<i>n</i> + <i>i</i>) zeroes between
* the decimal point and <i>s</i><sub>1</sub>.
* For example, 123 &times; 10<sup>-4</sup> is formatted as
* {@code 0.0123}.
* <li>Case 0 &le; <i>e</i> &lt; 7:
* <ul>
* <li>Subcase <i>i</i> &ge; 0:
* <i>d</i><sub><i>m</i></sub> is formatted as
* <i>s</i><sub>1</sub>&hellip;<i>s</i><sub><i>n</i></sub><!--
* --><code>0</code>&hellip;<code>0.0</code>,
* where there are exactly <i>i</i> zeroes
* between <i>s</i><sub><i>n</i></sub> and the decimal point.
* For example, 123 &times; 10<sup>2</sup> is formatted as
* {@code 12300.0}.
* <li>Subcase <i>i</i> &lt; 0:
* <i>d</i><sub><i>m</i></sub> is formatted as
* <i>s</i><sub>1</sub>&hellip;<!--
* --><i>s</i><sub><i>n</i>+<i>i</i></sub><code>.</code><!--
* --><i>s</i><sub><i>n</i>+<i>i</i>+1</sub>&hellip;<!--
* --><i>s</i><sub><i>n</i></sub>,
* where there are exactly -<i>i</i> digits to the right of
* the decimal point.
* For example, 123 &times; 10<sup>-1</sup> is formatted as
* {@code 12.3}.
* </ul>
* <li>Case <i>e</i> &lt; -3 or <i>e</i> &ge; 7:
* computerized scientific notation is used to format
* <i>d</i><sub><i>m</i></sub>.
* Here <i>e</i> is formatted as by {@link Integer#toString(int)}.
* <ul>
* <li>Subcase <i>n</i> = 1:
* <i>d</i><sub><i>m</i></sub> is formatted as
* <i>s</i><sub>1</sub><code>.0E</code><i>e</i>.
* For example, 1 &times; 10<sup>23</sup> is formatted as
* {@code 1.0E23}.
* <li>Subcase <i>n</i> &gt; 1:
* <i>d</i><sub><i>m</i></sub> is formatted as
* <i>s</i><sub>1</sub><code>.</code><i>s</i><sub>2</sub><!--
* -->&hellip;<i>s</i><sub><i>n</i></sub><code>E</code><i>e</i>.
* For example, 123 &times; 10<sup>-21</sup> is formatted as
* {@code 1.23E-19}.
* </ul>
* </ul>
* How many digits must be printed for the fractional part of
* <i>m</i> or <i>a</i>? 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 <i>x</i> is the
* exact mathematical value represented by the decimal
* representation produced by this method for a finite nonzero
* argument <i>f</i>. Then <i>f</i> must be the {@code float}
* value nearest to <i>x</i>; or, if two {@code float} values are
* equally close to <i>x</i>, then <i>f</i> must be one of
* them and the least significant bit of the significand of
* <i>f</i> must be {@code 0}.
*
* <p>To create localized string representations of a floating-point
* value, use subclasses of {@link java.text.NumberFormat}.
*
* @param f the float to be converted.
* @param f the {@code float} to be converted.
* @return a string representation of the argument.
*/
public static String toString(float f) {
return FloatingDecimal.toJavaFormatString(f);
return FloatToDecimal.toString(f);
}

/**
Expand Down
Loading