Skip to content

Commit 72bcf2a

Browse files
rgiuliettijddarcy
authored andcommitted
4511638: Double.toString(double) sometimes produces incorrect results
Reviewed-by: aturbanov, darcy, bpb
1 parent 2f19144 commit 72bcf2a

File tree

18 files changed

+4076
-121
lines changed

18 files changed

+4076
-121
lines changed

src/java.base/share/classes/java/lang/AbstractStringBuilder.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@
2525

2626
package java.lang;
2727

28-
import jdk.internal.math.FloatingDecimal;
28+
import jdk.internal.math.DoubleToDecimal;
29+
import jdk.internal.math.FloatToDecimal;
2930

31+
import java.io.IOException;
3032
import java.util.Arrays;
3133
import java.util.Spliterator;
3234
import java.util.stream.IntStream;
@@ -875,8 +877,13 @@ public AbstractStringBuilder append(long l) {
875877
* @return a reference to this object.
876878
*/
877879
public AbstractStringBuilder append(float f) {
878-
FloatingDecimal.appendTo(f,this);
880+
try {
881+
FloatToDecimal.appendTo(f, this);
882+
} catch (IOException e) {
883+
throw new AssertionError(e);
884+
}
879885
return this;
886+
880887
}
881888

882889
/**
@@ -892,7 +899,11 @@ public AbstractStringBuilder append(float f) {
892899
* @return a reference to this object.
893900
*/
894901
public AbstractStringBuilder append(double d) {
895-
FloatingDecimal.appendTo(d,this);
902+
try {
903+
DoubleToDecimal.appendTo(d, this);
904+
} catch (IOException e) {
905+
throw new AssertionError(e);
906+
}
896907
return this;
897908
}
898909

src/java.base/share/classes/java/lang/Double.java

Lines changed: 103 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
import jdk.internal.math.FloatingDecimal;
3434
import jdk.internal.math.DoubleConsts;
35+
import jdk.internal.math.DoubleToDecimal;
3536
import jdk.internal.vm.annotation.IntrinsicCandidate;
3637

3738
/**
@@ -280,39 +281,109 @@ public final class Double extends Number
280281
* {@code "-0.0"} and positive zero produces the result
281282
* {@code "0.0"}.
282283
*
283-
* <li>If <i>m</i> is greater than or equal to 10<sup>-3</sup> but less
284-
* than 10<sup>7</sup>, then it is represented as the integer part of
285-
* <i>m</i>, in decimal form with no leading zeroes, followed by
286-
* '{@code .}' ({@code '\u005Cu002E'}), followed by one or
287-
* more decimal digits representing the fractional part of <i>m</i>.
288-
*
289-
* <li>If <i>m</i> is less than 10<sup>-3</sup> or greater than or
290-
* equal to 10<sup>7</sup>, then it is represented in so-called
291-
* "computerized scientific notation." Let <i>n</i> be the unique
292-
* integer such that 10<sup><i>n</i></sup> &le; <i>m</i> {@literal <}
293-
* 10<sup><i>n</i>+1</sup>; then let <i>a</i> be the
294-
* mathematically exact quotient of <i>m</i> and
295-
* 10<sup><i>n</i></sup> so that 1 &le; <i>a</i> {@literal <} 10. The
296-
* magnitude is then represented as the integer part of <i>a</i>,
297-
* as a single decimal digit, followed by '{@code .}'
298-
* ({@code '\u005Cu002E'}), followed by decimal digits
299-
* representing the fractional part of <i>a</i>, followed by the
300-
* letter '{@code E}' ({@code '\u005Cu0045'}), followed
301-
* by a representation of <i>n</i> as a decimal integer, as
302-
* produced by the method {@link Integer#toString(int)}.
284+
* <li> Otherwise <i>m</i> is positive and finite.
285+
* It is converted to a string in two stages:
286+
* <ul>
287+
* <li> <em>Selection of a decimal</em>:
288+
* A well-defined decimal <i>d</i><sub><i>m</i></sub>
289+
* is selected to represent <i>m</i>.
290+
* This decimal is (almost always) the <em>shortest</em> one that
291+
* rounds to <i>m</i> according to the round to nearest
292+
* rounding policy of IEEE 754 floating-point arithmetic.
293+
* <li> <em>Formatting as a string</em>:
294+
* The decimal <i>d</i><sub><i>m</i></sub> is formatted as a string,
295+
* either in plain or in computerized scientific notation,
296+
* depending on its value.
297+
* </ul>
298+
* </ul>
299+
* </ul>
300+
*
301+
* <p>A <em>decimal</em> is a number of the form
302+
* <i>s</i>&times;10<sup><i>i</i></sup>
303+
* for some (unique) integers <i>s</i> &gt; 0 and <i>i</i> such that
304+
* <i>s</i> is not a multiple of 10.
305+
* These integers are the <em>significand</em> and
306+
* the <em>exponent</em>, respectively, of the decimal.
307+
* The <em>length</em> of the decimal is the (unique)
308+
* positive integer <i>n</i> meeting
309+
* 10<sup><i>n</i>-1</sup> &le; <i>s</i> &lt; 10<sup><i>n</i></sup>.
310+
*
311+
* <p>The decimal <i>d</i><sub><i>m</i></sub> for a finite positive <i>m</i>
312+
* is defined as follows:
313+
* <ul>
314+
* <li>Let <i>R</i> be the set of all decimals that round to <i>m</i>
315+
* according to the usual <em>round to nearest</em> rounding policy of
316+
* IEEE 754 floating-point arithmetic.
317+
* <li>Let <i>p</i> be the minimal length over all decimals in <i>R</i>.
318+
* <li>When <i>p</i> &ge; 2, let <i>T</i> be the set of all decimals
319+
* in <i>R</i> with length <i>p</i>.
320+
* Otherwise, let <i>T</i> be the set of all decimals
321+
* in <i>R</i> with length 1 or 2.
322+
* <li>Define <i>d</i><sub><i>m</i></sub> as the decimal in <i>T</i>
323+
* that is closest to <i>m</i>.
324+
* Or if there are two such decimals in <i>T</i>,
325+
* select the one with the even significand.
326+
* </ul>
327+
*
328+
* <p>The (uniquely) selected decimal <i>d</i><sub><i>m</i></sub>
329+
* is then formatted.
330+
* Let <i>s</i>, <i>i</i> and <i>n</i> be the significand, exponent and
331+
* length of <i>d</i><sub><i>m</i></sub>, respectively.
332+
* Further, let <i>e</i> = <i>n</i> + <i>i</i> - 1 and let
333+
* <i>s</i><sub>1</sub>&hellip;<i>s</i><sub><i>n</i></sub>
334+
* be the usual decimal expansion of <i>s</i>.
335+
* Note that <i>s</i><sub>1</sub> &ne; 0
336+
* and <i>s</i><sub><i>n</i></sub> &ne; 0.
337+
* Below, the decimal point {@code '.'} is {@code '\u005Cu002E'}
338+
* and the exponent indicator {@code 'E'} is {@code '\u005Cu0045'}.
339+
* <ul>
340+
* <li>Case -3 &le; <i>e</i> &lt; 0:
341+
* <i>d</i><sub><i>m</i></sub> is formatted as
342+
* <code>0.0</code>&hellip;<code>0</code><!--
343+
* --><i>s</i><sub>1</sub>&hellip;<i>s</i><sub><i>n</i></sub>,
344+
* where there are exactly -(<i>n</i> + <i>i</i>) zeroes between
345+
* the decimal point and <i>s</i><sub>1</sub>.
346+
* For example, 123 &times; 10<sup>-4</sup> is formatted as
347+
* {@code 0.0123}.
348+
* <li>Case 0 &le; <i>e</i> &lt; 7:
349+
* <ul>
350+
* <li>Subcase <i>i</i> &ge; 0:
351+
* <i>d</i><sub><i>m</i></sub> is formatted as
352+
* <i>s</i><sub>1</sub>&hellip;<i>s</i><sub><i>n</i></sub><!--
353+
* --><code>0</code>&hellip;<code>0.0</code>,
354+
* where there are exactly <i>i</i> zeroes
355+
* between <i>s</i><sub><i>n</i></sub> and the decimal point.
356+
* For example, 123 &times; 10<sup>2</sup> is formatted as
357+
* {@code 12300.0}.
358+
* <li>Subcase <i>i</i> &lt; 0:
359+
* <i>d</i><sub><i>m</i></sub> is formatted as
360+
* <i>s</i><sub>1</sub>&hellip;<!--
361+
* --><i>s</i><sub><i>n</i>+<i>i</i></sub><code>.</code><!--
362+
* --><i>s</i><sub><i>n</i>+<i>i</i>+1</sub>&hellip;<!--
363+
* --><i>s</i><sub><i>n</i></sub>,
364+
* where there are exactly -<i>i</i> digits to the right of
365+
* the decimal point.
366+
* For example, 123 &times; 10<sup>-1</sup> is formatted as
367+
* {@code 12.3}.
368+
* </ul>
369+
* <li>Case <i>e</i> &lt; -3 or <i>e</i> &ge; 7:
370+
* computerized scientific notation is used to format
371+
* <i>d</i><sub><i>m</i></sub>.
372+
* Here <i>e</i> is formatted as by {@link Integer#toString(int)}.
373+
* <ul>
374+
* <li>Subcase <i>n</i> = 1:
375+
* <i>d</i><sub><i>m</i></sub> is formatted as
376+
* <i>s</i><sub>1</sub><code>.0E</code><i>e</i>.
377+
* For example, 1 &times; 10<sup>23</sup> is formatted as
378+
* {@code 1.0E23}.
379+
* <li>Subcase <i>n</i> &gt; 1:
380+
* <i>d</i><sub><i>m</i></sub> is formatted as
381+
* <i>s</i><sub>1</sub><code>.</code><i>s</i><sub>2</sub><!--
382+
* -->&hellip;<i>s</i><sub><i>n</i></sub><code>E</code><i>e</i>.
383+
* For example, 123 &times; 10<sup>-21</sup> is formatted as
384+
* {@code 1.23E-19}.
303385
* </ul>
304386
* </ul>
305-
* How many digits must be printed for the fractional part of
306-
* <i>m</i> or <i>a</i>? There must be at least one digit to represent
307-
* the fractional part, and beyond that as many, but only as many, more
308-
* digits as are needed to uniquely distinguish the argument value from
309-
* adjacent values of type {@code double}. That is, suppose that
310-
* <i>x</i> is the exact mathematical value represented by the decimal
311-
* representation produced by this method for a finite nonzero argument
312-
* <i>d</i>. Then <i>d</i> must be the {@code double} value nearest
313-
* to <i>x</i>; or if two {@code double} values are equally close
314-
* to <i>x</i>, then <i>d</i> must be one of them and the least
315-
* significant bit of the significand of <i>d</i> must be {@code 0}.
316387
*
317388
* <p>To create localized string representations of a floating-point
318389
* value, use subclasses of {@link java.text.NumberFormat}.
@@ -321,7 +392,7 @@ public final class Double extends Number
321392
* @return a string representation of the argument.
322393
*/
323394
public static String toString(double d) {
324-
return FloatingDecimal.toJavaFormatString(d);
395+
return DoubleToDecimal.toString(d);
325396
}
326397

327398
/**

src/java.base/share/classes/java/lang/Float.java

Lines changed: 104 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import java.util.Optional;
3232

3333
import jdk.internal.math.FloatingDecimal;
34+
import jdk.internal.math.FloatToDecimal;
3435
import jdk.internal.vm.annotation.IntrinsicCandidate;
3536

3637
/**
@@ -189,53 +190,119 @@ public final class Float extends Number
189190
* {@code "0.0"}; thus, negative zero produces the result
190191
* {@code "-0.0"} and positive zero produces the result
191192
* {@code "0.0"}.
192-
* <li> If <i>m</i> is greater than or equal to 10<sup>-3</sup> but
193-
* less than 10<sup>7</sup>, then it is represented as the
194-
* integer part of <i>m</i>, in decimal form with no leading
195-
* zeroes, followed by '{@code .}'
196-
* ({@code '\u005Cu002E'}), followed by one or more
197-
* decimal digits representing the fractional part of
198-
* <i>m</i>.
199-
* <li> If <i>m</i> is less than 10<sup>-3</sup> or greater than or
200-
* equal to 10<sup>7</sup>, then it is represented in
201-
* so-called "computerized scientific notation." Let <i>n</i>
202-
* be the unique integer such that 10<sup><i>n</i> </sup>&le;
203-
* <i>m</i> {@literal <} 10<sup><i>n</i>+1</sup>; then let <i>a</i>
204-
* be the mathematically exact quotient of <i>m</i> and
205-
* 10<sup><i>n</i></sup> so that 1 &le; <i>a</i> {@literal <} 10.
206-
* The magnitude is then represented as the integer part of
207-
* <i>a</i>, as a single decimal digit, followed by
208-
* '{@code .}' ({@code '\u005Cu002E'}), followed by
209-
* decimal digits representing the fractional part of
210-
* <i>a</i>, followed by the letter '{@code E}'
211-
* ({@code '\u005Cu0045'}), followed by a representation
212-
* of <i>n</i> as a decimal integer, as produced by the
213-
* method {@link java.lang.Integer#toString(int)}.
214193
*
194+
* <li> Otherwise <i>m</i> is positive and finite.
195+
* It is converted to a string in two stages:
196+
* <ul>
197+
* <li> <em>Selection of a decimal</em>:
198+
* A well-defined decimal <i>d</i><sub><i>m</i></sub>
199+
* is selected to represent <i>m</i>.
200+
* This decimal is (almost always) the <em>shortest</em> one that
201+
* rounds to <i>m</i> according to the round to nearest
202+
* rounding policy of IEEE 754 floating-point arithmetic.
203+
* <li> <em>Formatting as a string</em>:
204+
* The decimal <i>d</i><sub><i>m</i></sub> is formatted as a string,
205+
* either in plain or in computerized scientific notation,
206+
* depending on its value.
207+
* </ul>
208+
* </ul>
209+
* </ul>
210+
*
211+
* <p>A <em>decimal</em> is a number of the form
212+
* <i>s</i>&times;10<sup><i>i</i></sup>
213+
* for some (unique) integers <i>s</i> &gt; 0 and <i>i</i> such that
214+
* <i>s</i> is not a multiple of 10.
215+
* These integers are the <em>significand</em> and
216+
* the <em>exponent</em>, respectively, of the decimal.
217+
* The <em>length</em> of the decimal is the (unique)
218+
* positive integer <i>n</i> meeting
219+
* 10<sup><i>n</i>-1</sup> &le; <i>s</i> &lt; 10<sup><i>n</i></sup>.
220+
*
221+
* <p>The decimal <i>d</i><sub><i>m</i></sub> for a finite positive <i>m</i>
222+
* is defined as follows:
223+
* <ul>
224+
* <li>Let <i>R</i> be the set of all decimals that round to <i>m</i>
225+
* according to the usual <em>round to nearest</em> rounding policy of
226+
* IEEE 754 floating-point arithmetic.
227+
* <li>Let <i>p</i> be the minimal length over all decimals in <i>R</i>.
228+
* <li>When <i>p</i> &ge; 2, let <i>T</i> be the set of all decimals
229+
* in <i>R</i> with length <i>p</i>.
230+
* Otherwise, let <i>T</i> be the set of all decimals
231+
* in <i>R</i> with length 1 or 2.
232+
* <li>Define <i>d</i><sub><i>m</i></sub> as the decimal in <i>T</i>
233+
* that is closest to <i>m</i>.
234+
* Or if there are two such decimals in <i>T</i>,
235+
* select the one with the even significand.
236+
* </ul>
237+
*
238+
* <p>The (uniquely) selected decimal <i>d</i><sub><i>m</i></sub>
239+
* is then formatted.
240+
* Let <i>s</i>, <i>i</i> and <i>n</i> be the significand, exponent and
241+
* length of <i>d</i><sub><i>m</i></sub>, respectively.
242+
* Further, let <i>e</i> = <i>n</i> + <i>i</i> - 1 and let
243+
* <i>s</i><sub>1</sub>&hellip;<i>s</i><sub><i>n</i></sub>
244+
* be the usual decimal expansion of <i>s</i>.
245+
* Note that <i>s</i><sub>1</sub> &ne; 0
246+
* and <i>s</i><sub><i>n</i></sub> &ne; 0.
247+
* Below, the decimal point {@code '.'} is {@code '\u005Cu002E'}
248+
* and the exponent indicator {@code 'E'} is {@code '\u005Cu0045'}.
249+
* <ul>
250+
* <li>Case -3 &le; <i>e</i> &lt; 0:
251+
* <i>d</i><sub><i>m</i></sub> is formatted as
252+
* <code>0.0</code>&hellip;<code>0</code><!--
253+
* --><i>s</i><sub>1</sub>&hellip;<i>s</i><sub><i>n</i></sub>,
254+
* where there are exactly -(<i>n</i> + <i>i</i>) zeroes between
255+
* the decimal point and <i>s</i><sub>1</sub>.
256+
* For example, 123 &times; 10<sup>-4</sup> is formatted as
257+
* {@code 0.0123}.
258+
* <li>Case 0 &le; <i>e</i> &lt; 7:
259+
* <ul>
260+
* <li>Subcase <i>i</i> &ge; 0:
261+
* <i>d</i><sub><i>m</i></sub> is formatted as
262+
* <i>s</i><sub>1</sub>&hellip;<i>s</i><sub><i>n</i></sub><!--
263+
* --><code>0</code>&hellip;<code>0.0</code>,
264+
* where there are exactly <i>i</i> zeroes
265+
* between <i>s</i><sub><i>n</i></sub> and the decimal point.
266+
* For example, 123 &times; 10<sup>2</sup> is formatted as
267+
* {@code 12300.0}.
268+
* <li>Subcase <i>i</i> &lt; 0:
269+
* <i>d</i><sub><i>m</i></sub> is formatted as
270+
* <i>s</i><sub>1</sub>&hellip;<!--
271+
* --><i>s</i><sub><i>n</i>+<i>i</i></sub><code>.</code><!--
272+
* --><i>s</i><sub><i>n</i>+<i>i</i>+1</sub>&hellip;<!--
273+
* --><i>s</i><sub><i>n</i></sub>,
274+
* where there are exactly -<i>i</i> digits to the right of
275+
* the decimal point.
276+
* For example, 123 &times; 10<sup>-1</sup> is formatted as
277+
* {@code 12.3}.
278+
* </ul>
279+
* <li>Case <i>e</i> &lt; -3 or <i>e</i> &ge; 7:
280+
* computerized scientific notation is used to format
281+
* <i>d</i><sub><i>m</i></sub>.
282+
* Here <i>e</i> is formatted as by {@link Integer#toString(int)}.
283+
* <ul>
284+
* <li>Subcase <i>n</i> = 1:
285+
* <i>d</i><sub><i>m</i></sub> is formatted as
286+
* <i>s</i><sub>1</sub><code>.0E</code><i>e</i>.
287+
* For example, 1 &times; 10<sup>23</sup> is formatted as
288+
* {@code 1.0E23}.
289+
* <li>Subcase <i>n</i> &gt; 1:
290+
* <i>d</i><sub><i>m</i></sub> is formatted as
291+
* <i>s</i><sub>1</sub><code>.</code><i>s</i><sub>2</sub><!--
292+
* -->&hellip;<i>s</i><sub><i>n</i></sub><code>E</code><i>e</i>.
293+
* For example, 123 &times; 10<sup>-21</sup> is formatted as
294+
* {@code 1.23E-19}.
215295
* </ul>
216296
* </ul>
217-
* How many digits must be printed for the fractional part of
218-
* <i>m</i> or <i>a</i>? There must be at least one digit
219-
* to represent the fractional part, and beyond that as many, but
220-
* only as many, more digits as are needed to uniquely distinguish
221-
* the argument value from adjacent values of type
222-
* {@code float}. That is, suppose that <i>x</i> is the
223-
* exact mathematical value represented by the decimal
224-
* representation produced by this method for a finite nonzero
225-
* argument <i>f</i>. Then <i>f</i> must be the {@code float}
226-
* value nearest to <i>x</i>; or, if two {@code float} values are
227-
* equally close to <i>x</i>, then <i>f</i> must be one of
228-
* them and the least significant bit of the significand of
229-
* <i>f</i> must be {@code 0}.
230297
*
231298
* <p>To create localized string representations of a floating-point
232299
* value, use subclasses of {@link java.text.NumberFormat}.
233300
*
234-
* @param f the float to be converted.
301+
* @param f the {@code float} to be converted.
235302
* @return a string representation of the argument.
236303
*/
237304
public static String toString(float f) {
238-
return FloatingDecimal.toJavaFormatString(f);
305+
return FloatToDecimal.toString(f);
239306
}
240307

241308
/**

0 commit comments

Comments
 (0)