• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /*
25  * @test
26  * @bug 4160406 4705734 4707389 4826774 4895911 4421494 6358355 7021568 7039369 4396272
27  * @summary Test for Double.parseDouble method and acceptance regex
28  */
29 
30 package test.java.lang.Double;
31 
32 import java.math.BigDecimal;
33 import java.math.BigInteger;
34 import java.util.regex.*;
35 
36 public class ParseDouble {
37 
38     private static final BigDecimal HALF = BigDecimal.valueOf(0.5);
39 
fail(String val, double n)40     private static void fail(String val, double n) {
41         throw new RuntimeException("Double.parseDouble failed. String:" +
42                                                 val + " Result:" + n);
43     }
44 
check(String val)45     private static void check(String val) {
46         double n = Double.parseDouble(val);
47         boolean isNegativeN = n < 0 || n == 0 && 1/n < 0;
48         double na = Math.abs(n);
49         String s = val.trim().toLowerCase();
50         switch (s.charAt(s.length() - 1)) {
51             case 'd':
52             case 'f':
53                 s = s.substring(0, s.length() - 1);
54                 break;
55         }
56         boolean isNegative = false;
57         if (s.charAt(0) == '+') {
58             s = s.substring(1);
59         } else if (s.charAt(0) == '-') {
60             s = s.substring(1);
61             isNegative = true;
62         }
63         if (s.equals("nan")) {
64             if (!Double.isNaN(n)) {
65                 fail(val, n);
66             }
67             return;
68         }
69         if (Double.isNaN(n)) {
70             fail(val, n);
71         }
72         if (isNegativeN != isNegative)
73             fail(val, n);
74         if (s.equals("infinity")) {
75             if (na != Double.POSITIVE_INFINITY) {
76                 fail(val, n);
77             }
78             return;
79         }
80         BigDecimal bd;
81         if (s.startsWith("0x")) {
82             s = s.substring(2);
83             int indP = s.indexOf('p');
84             long exp = Long.parseLong(s.substring(indP + 1));
85             int indD = s.indexOf('.');
86             String significand;
87             if (indD >= 0) {
88                 significand = s.substring(0, indD) + s.substring(indD + 1, indP);
89                 exp -= 4*(indP - indD - 1);
90             } else {
91                 significand = s.substring(0, indP);
92             }
93             bd = new BigDecimal(new BigInteger(significand, 16));
94             if (exp >= 0) {
95                 bd = bd.multiply(BigDecimal.valueOf(2).pow((int)exp));
96             } else {
97                 bd = bd.divide(BigDecimal.valueOf(2).pow((int)-exp));
98             }
99         } else {
100             bd = new BigDecimal(s);
101         }
102         BigDecimal l, u;
103         if (Double.isInfinite(na)) {
104             l = new BigDecimal(Double.MAX_VALUE).add(new BigDecimal(Math.ulp(Double.MAX_VALUE)).multiply(HALF));
105             u = null;
106         } else {
107             l = new BigDecimal(na).subtract(new BigDecimal(Math.ulp(Math.nextUp(-na))).multiply(HALF));
108             u = new BigDecimal(na).add(new BigDecimal(Math.ulp(n)).multiply(HALF));
109         }
110         int cmpL = bd.compareTo(l);
111         int cmpU = u != null ? bd.compareTo(u) : -1;
112         if ((Double.doubleToLongBits(n) & 1) != 0) {
113             if (cmpL <= 0 || cmpU >= 0) {
114                 fail(val, n);
115             }
116         } else {
117             if (cmpL < 0 || cmpU > 0) {
118                 fail(val, n);
119             }
120         }
121     }
122 
check(String val, double expected)123     private static void check(String val, double expected) {
124         double n = Double.parseDouble(val);
125         if (n != expected)
126             fail(val, n);
127         check(val);
128     }
129 
rudimentaryTest()130     private static void rudimentaryTest() {
131         check(new String(""+Double.MIN_VALUE), Double.MIN_VALUE);
132         check(new String(""+Double.MAX_VALUE), Double.MAX_VALUE);
133 
134         check("10",     (double)  10.0);
135         check("10.0",   (double)  10.0);
136         check("10.01",  (double)  10.01);
137 
138         check("-10",    (double) -10.0);
139         check("-10.00", (double) -10.0);
140         check("-10.01", (double) -10.01);
141     }
142 
143 
144     static  String badStrings[] = {
145         "",
146         "+",
147         "-",
148         "+e",
149         "-e",
150         "+e170",
151         "-e170",
152 
153         // Make sure intermediate white space is not deleted.
154         "1234   e10",
155         "-1234   e10",
156 
157         // Control characters in the interior of a string are not legal
158         "1\u0007e1",
159         "1e\u00071",
160 
161         // NaN and infinity can't have trailing type suffices or exponents
162         "NaNf",
163         "NaNF",
164         "NaNd",
165         "NaND",
166         "-NaNf",
167         "-NaNF",
168         "-NaNd",
169         "-NaND",
170         "+NaNf",
171         "+NaNF",
172         "+NaNd",
173         "+NaND",
174         "Infinityf",
175         "InfinityF",
176         "Infinityd",
177         "InfinityD",
178         "-Infinityf",
179         "-InfinityF",
180         "-Infinityd",
181         "-InfinityD",
182         "+Infinityf",
183         "+InfinityF",
184         "+Infinityd",
185         "+InfinityD",
186 
187         "NaNe10",
188         "-NaNe10",
189         "+NaNe10",
190         "Infinitye10",
191         "-Infinitye10",
192         "+Infinitye10",
193 
194         // Non-ASCII digits are not recognized
195         // Android-removed: non-ASCII digits tests
196         // "\u0661e\u0661", // 1e1 in Arabic-Indic digits
197         // "\u06F1e\u06F1", // 1e1 in Extended Arabic-Indic digits
198         // "\u0967e\u0967", // 1e1 in Devanagari digits
199 
200         // JCK test lex03592m3
201         ".",
202 
203         // JCK test lex03592m4
204         "e42",
205 
206         // JCK test lex03592m5
207         ".e42",
208 
209         // JCK test lex03592m6
210         "d",
211 
212         // JCK test lex03592m7
213         ".d",
214 
215         // JCK test lex03592m8
216         "e42d",
217 
218         // JCK test lex03592m9
219         ".e42d",
220 
221         // JCK test lex03593m10
222         "1A01.01125e-10d",
223 
224         // JCK test lex03593m11
225         "2;3.01125e-10d",
226 
227         // JCK test lex03593m12
228         "1_34.01125e-10d",
229 
230         // JCK test lex03593m14
231         "202..01125e-10d",
232 
233         // JCK test lex03593m15
234         "202,01125e-10d",
235 
236         // JCK test lex03593m16
237         "202.03b4e-10d",
238 
239         // JCK test lex03593m18
240         "202.06_3e-10d",
241 
242         // JCK test lex03593m20
243         "202.01125e-f0d",
244 
245         // JCK test lex03593m21
246         "202.01125e_3d",
247 
248         // JCK test lex03593m22
249         "202.01125e -5d",
250 
251         // JCK test lex03593m24
252         "202.01125e-10r",
253 
254         // JCK test lex03593m25
255         "202.01125e-10ff",
256 
257         // JCK test lex03593m26
258         "1234L.01",
259 
260         // JCK test lex03593m27
261         "12ee-2",
262 
263         // JCK test lex03593m28
264         "12e-2.2.2",
265 
266         // JCK test lex03593m29
267         "12.01e+",
268 
269         // JCK test lex03593m30
270         "12.01E",
271 
272         // Bad hexadecimal-style strings
273 
274         // Two leading zeros
275         "00x1.0p1",
276 
277         // Must have hex specifier
278         "1.0p1",
279         "00010p1",
280         "deadbeefp1",
281 
282         // Need an explicit fully-formed exponent
283         "0x1.0p",
284         "0x1.0",
285 
286         // Exponent must be in decimal
287         "0x1.0pa",
288         "0x1.0pf",
289 
290         // Exponent separated by "p"
291         "0x1.0e22",
292         "0x1.0e22",
293 
294         // Need a signifcand
295         "0xp22"
296     };
297 
298     static String goodStrings[] = {
299         "NaN",
300         "+NaN",
301         "-NaN",
302         "Infinity",
303         "+Infinity",
304         "-Infinity",
305         "1.1e-23f",
306         ".1e-23f",
307         "1e-23",
308         "1f",
309         "0",
310         "-0",
311         "+0",
312         "00",
313         "00",
314         "-00",
315         "+00",
316         "0000000000",
317         "-0000000000",
318         "+0000000000",
319         "1",
320         "2",
321         "1234",
322         "-1234",
323         "+1234",
324         "2147483647",   // Integer.MAX_VALUE
325         "2147483648",
326         "-2147483648",  // Integer.MIN_VALUE
327         "-2147483649",
328 
329         "16777215",
330         "16777216",     // 2^24
331         "16777217",
332 
333         "-16777215",
334         "-16777216",    // -2^24
335         "-16777217",
336 
337         "9007199254740991",
338         "9007199254740992",     // 2^53
339         "9007199254740993",
340 
341         "-9007199254740991",
342         "-9007199254740992",    // -2^53
343         "-9007199254740993",
344 
345         "9223372036854775807",
346         "9223372036854775808",  // Long.MAX_VALUE
347         "9223372036854775809",
348 
349         "-9223372036854775808",
350         "-9223372036854775809", // Long.MIN_VALUE
351         "-9223372036854775810",
352 
353         // Culled from JCK test lex03591m1
354         "54.07140d",
355         "7.01e-324d",
356         "2147483647.01d",
357         "1.2147483647f",
358         "000000000000000000000000001.F",
359         "1.00000000000000000000000000e-2F",
360 
361         // Culled from JCK test lex03592m2
362         "2.",
363         ".0909",
364         "122112217090.0",
365         "7090e-5",
366         "2.E-20",
367         ".0909e42",
368         "122112217090.0E+100",
369         "7090f",
370         "2.F",
371         ".0909d",
372         "122112217090.0D",
373         "7090e-5f",
374         "2.E-20F",
375         ".0909e42d",
376         "122112217090.0E+100D",
377 
378         // Culled from JCK test lex03594m31 -- unicode escapes
379         "\u0035\u0031\u0034\u0039\u0032\u0033\u0036\u0037\u0038\u0030.1102E-209D",
380         "1290873\u002E12301e100",
381         "1.1E-10\u0066",
382 
383         // Culled from JCK test lex03595m1
384         "0.0E-10",
385         "1E10",
386 
387         // Culled from JCK test lex03691m1
388         "0.f",
389         "1f",
390         "0.F",
391         "1F",
392         "0.12d",
393         "1e-0d",
394         "12.e+1D",
395         "0e-0D",
396         "12.e+01",
397         "1e-01",
398 
399         // Good hex strings
400         // Vary capitalization of separators.
401 
402         "0x1p1",
403         "0X1p1",
404         "0x1P1",
405         "0X1P1",
406         "0x1p1f",
407         "0X1p1f",
408         "0x1P1f",
409         "0X1P1f",
410         "0x1p1F",
411         "0X1p1F",
412         "0x1P1F",
413         "0X1P1F",
414         "0x1p1d",
415         "0X1p1d",
416         "0x1P1d",
417         "0X1P1d",
418         "0x1p1D",
419         "0X1p1D",
420         "0x1P1D",
421         "0X1P1D",
422 
423         "-0x1p1",
424         "-0X1p1",
425         "-0x1P1",
426         "-0X1P1",
427         "-0x1p1f",
428         "-0X1p1f",
429         "-0x1P1f",
430         "-0X1P1f",
431         "-0x1p1F",
432         "-0X1p1F",
433         "-0x1P1F",
434         "-0X1P1F",
435         "-0x1p1d",
436         "-0X1p1d",
437         "-0x1P1d",
438         "-0X1P1d",
439         "-0x1p1D",
440         "-0X1p1D",
441         "-0x1P1D",
442         "-0X1P1D",
443 
444         "0x1p-1",
445         "0X1p-1",
446         "0x1P-1",
447         "0X1P-1",
448         "0x1p-1f",
449         "0X1p-1f",
450         "0x1P-1f",
451         "0X1P-1f",
452         "0x1p-1F",
453         "0X1p-1F",
454         "0x1P-1F",
455         "0X1P-1F",
456         "0x1p-1d",
457         "0X1p-1d",
458         "0x1P-1d",
459         "0X1P-1d",
460         "0x1p-1D",
461         "0X1p-1D",
462         "0x1P-1D",
463         "0X1P-1D",
464 
465         "-0x1p-1",
466         "-0X1p-1",
467         "-0x1P-1",
468         "-0X1P-1",
469         "-0x1p-1f",
470         "-0X1p-1f",
471         "-0x1P-1f",
472         "-0X1P-1f",
473         "-0x1p-1F",
474         "-0X1p-1F",
475         "-0x1P-1F",
476         "-0X1P-1F",
477         "-0x1p-1d",
478         "-0X1p-1d",
479         "-0x1P-1d",
480         "-0X1P-1d",
481         "-0x1p-1D",
482         "-0X1p-1D",
483         "-0x1P-1D",
484         "-0X1P-1D",
485 
486 
487         // Try different significand combinations
488         "0xap1",
489         "0xbp1",
490         "0xcp1",
491         "0xdp1",
492         "0xep1",
493         "0xfp1",
494 
495         "0x1p1",
496         "0x.1p1",
497         "0x1.1p1",
498 
499         "0x001p23",
500         "0x00.1p1",
501         "0x001.1p1",
502 
503         "0x100p1",
504         "0x.100p1",
505         "0x1.100p1",
506 
507         "0x00100p1",
508         "0x00.100p1",
509         "0x001.100p1",
510 
511         // Limits
512 
513         "1.7976931348623157E308",     // Double.MAX_VALUE
514         "4.9e-324",                   // Double.MIN_VALUE
515         "2.2250738585072014e-308",    // Double.MIN_NORMAL
516 
517         "2.2250738585072012e-308",    // near Double.MIN_NORMAL
518 
519         "1.7976931348623158e+308",    // near MAX_VALUE + ulp(MAX_VALUE)/2
520         "1.7976931348623159e+308",    // near MAX_VALUE + ulp(MAX_VALUE)
521 
522         "2.4703282292062329e-324",    // above MIN_VALUE/2
523         "2.4703282292062327e-324",    // MIN_VALUE/2
524         "2.4703282292062325e-324",    // below MIN_VALUE/2
525 
526         // 1e308 with leading zeros
527 
528         "0.0000000000001e321",
529         "00.000000000000000001e326",
530         "00000.000000000000000001e326",
531         "000.0000000000000000001e327",
532         "0.00000000000000000001e328",
533     };
534 
535     static String paddedBadStrings[];
536     static String paddedGoodStrings[];
537     static {
538         String pad = " \t\n\r\f\u0001\u000b\u001f";
539         paddedBadStrings = new String[badStrings.length];
540         for(int i = 0 ; i <  badStrings.length; i++)
541             paddedBadStrings[i] = pad + badStrings[i] + pad;
542 
543         paddedGoodStrings = new String[goodStrings.length];
544         for(int i = 0 ; i <  goodStrings.length; i++)
545             paddedGoodStrings[i] = pad + goodStrings[i] + pad;
546 
547     }
548 
549 
550     /*
551      * Throws an exception if <code>Input</code> is
552      * <code>exceptionalInput</code> and {@link Double.parseDouble
553      * parseDouble} does <em>not</em> throw an exception or if
554      * <code>Input</code> is not <code>exceptionalInput</code> and
555      * <code>parseDouble</code> throws an exception.  This method does
556      * not attempt to test whether the string is converted to the
557      * proper value; just whether the input is accepted appropriately
558      * or not.
559      */
testParsing(String [] input, boolean exceptionalInput)560     private static void testParsing(String [] input,
561                                     boolean exceptionalInput) {
562         for (String s : input) {
563             try {
564                 Double.parseDouble(s);
565                 check(s);
566             } catch (NumberFormatException e) {
567                 if (!exceptionalInput) {
568                     throw new RuntimeException("Double.parseDouble rejected " +
569                                                "good string `" + s +
570                                                "'.");
571                 }
572                 continue;
573             }
574             if (exceptionalInput) {
575                 throw new RuntimeException("Double.parseDouble accepted " +
576                                            "bad string `" + s +
577                                            "'.");
578             }
579         }
580     }
581 
582     /*
583      * Throws an exception if <code>Input</code> is
584      * <code>exceptionalInput</code> and the regular expression
585      * matches one of the strings or if <code>Input</code> is not
586      * <code>exceptionalInput</code> and the regular expression fails
587      * to match an input string.
588      */
testRegex(String [] input, boolean exceptionalInput)589     private static void testRegex(String [] input, boolean exceptionalInput) {
590         /*
591          * The regex below is taken from the JavaDoc for
592          * Double.valueOf.
593          */
594 
595         final String Digits     = "(\\p{Digit}+)";
596         final String HexDigits  = "(\\p{XDigit}+)";
597         // an exponent is 'e' or 'E' followed by an optionally
598         // signed decimal integer.
599         final String Exp        = "[eE][+-]?"+Digits;
600         final String fpRegex    =
601             ("[\\x00-\\x20]*"+  // Optional leading "whitespace"
602              "[+-]?(" + // Optional sign character
603              "NaN|" +           // "NaN" string
604              "Infinity|" +      // "Infinity" string
605 
606              // A floating-point string representing a finite positive
607              // number without a leading sign has at most five basic pieces:
608              // Digits . Digits ExponentPart FloatTypeSuffix
609              //
610              // Since this method allows integer-only strings as input
611              // in addition to strings of floating-point literals, the
612              // two sub-patterns below are simplifications of the grammar
613              // productions from the Java Language Specification, 2nd
614              // edition, section 3.10.2.
615 
616 
617              // A decimal floating-point string representing a finite positive
618              // number without a leading sign has at most five basic pieces:
619              // Digits . Digits ExponentPart FloatTypeSuffix
620              //
621              // Since this method allows integer-only strings as input
622              // in addition to strings of floating-point literals, the
623              // two sub-patterns below are simplifications of the grammar
624              // productions from the Java Language Specification, 2nd
625              // edition, section 3.10.2.
626 
627              // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
628              "(((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+
629 
630              // . Digits ExponentPart_opt FloatTypeSuffix_opt
631              "(\\.("+Digits+")("+Exp+")?))|"+
632 
633             // Hexadecimal strings
634             "((" +
635              // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
636              "(0[xX]" + HexDigits + "(\\.)?)|" +
637 
638              // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
639              "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" +
640 
641              ")[pP][+-]?" + Digits + "))" +
642              "[fFdD]?))" +
643              "[\\x00-\\x20]*");// Optional trailing "whitespace"
644         Pattern fpPattern = Pattern.compile(fpRegex);
645 
646         for(int i = 0; i < input.length; i++) {
647              Matcher m = fpPattern.matcher(input[i]);
648              if (m.matches() != ! exceptionalInput) {
649                  throw new RuntimeException("Regular expression " +
650                                             (exceptionalInput?
651                                              "accepted bad":
652                                              "rejected good") +
653                                             " string `" +
654                                             input[i] + "'.");
655              }
656         }
657 
658     }
659 
660     /**
661      * For each subnormal power of two, test at boundaries of
662      * region that should convert to that value.
663      */
testSubnormalPowers()664     private static void testSubnormalPowers() {
665         boolean failed = false;
666         BigDecimal TWO = BigDecimal.valueOf(2);
667         // An ulp is the same for all subnormal values
668         BigDecimal ulp_BD = new BigDecimal(Double.MIN_VALUE);
669 
670         // Test subnormal powers of two (except Double.MIN_VALUE)
671         for(int i = -1073; i <= -1022; i++) {
672             double d = Math.scalb(1.0, i);
673 
674             /*
675              * The region [d - ulp/2, d + ulp/2] should round to d.
676              */
677             BigDecimal d_BD = new BigDecimal(d);
678 
679             BigDecimal lowerBound = d_BD.subtract(ulp_BD.divide(TWO));
680             BigDecimal upperBound = d_BD.add(ulp_BD.divide(TWO));
681 
682             double convertedLowerBound = Double.parseDouble(lowerBound.toString());
683             double convertedUpperBound = Double.parseDouble(upperBound.toString());
684             if (convertedLowerBound != d) {
685                 failed = true;
686                 System.out.printf("2^%d lowerBound converts as %a %s%n",
687                                   i, convertedLowerBound, lowerBound);
688             }
689             if (convertedUpperBound != d) {
690                 failed = true;
691                 System.out.printf("2^%d upperBound converts as %a %s%n",
692                                   i, convertedUpperBound, upperBound);
693             }
694         }
695         /*
696          * Double.MIN_VALUE
697          * The region ]0.5*Double.MIN_VALUE, 1.5*Double.MIN_VALUE[ should round to Double.MIN_VALUE .
698          */
699         BigDecimal minValue = new BigDecimal(Double.MIN_VALUE);
700         if (Double.parseDouble(minValue.multiply(new BigDecimal(0.5)).toString()) != 0.0) {
701             failed = true;
702             System.out.printf("0.5*MIN_VALUE doesn't convert 0%n");
703         }
704         if (Double.parseDouble(minValue.multiply(new BigDecimal(0.50000000001)).toString()) != Double.MIN_VALUE) {
705             failed = true;
706             System.out.printf("0.50000000001*MIN_VALUE doesn't convert to MIN_VALUE%n");
707         }
708         if (Double.parseDouble(minValue.multiply(new BigDecimal(1.49999999999)).toString()) != Double.MIN_VALUE) {
709             failed = true;
710             System.out.printf("1.49999999999*MIN_VALUE doesn't convert to MIN_VALUE%n");
711         }
712         if (Double.parseDouble(minValue.multiply(new BigDecimal(1.5)).toString()) != 2*Double.MIN_VALUE) {
713             failed = true;
714             System.out.printf("1.5*MIN_VALUE doesn't convert to 2*MIN_VALUE%n");
715         }
716 
717         if (failed)
718             throw new RuntimeException("Inconsistent conversion");
719     }
720 
721     /**
722      * For each power of two, test at boundaries of
723      * region that should convert to that value.
724      */
testPowers()725     private static void testPowers() {
726         for(int i = -1074; i <= +1023; i++) {
727             double d = Math.scalb(1.0, i);
728             BigDecimal d_BD = new BigDecimal(d);
729 
730             BigDecimal lowerBound = d_BD.subtract(new BigDecimal(Math.ulp(Math.nextUp(-d))).multiply(HALF));
731             BigDecimal upperBound = d_BD.add(new BigDecimal(Math.ulp(d)).multiply(HALF));
732 
733             check(lowerBound.toString());
734             check(upperBound.toString());
735         }
736         check(new BigDecimal(Double.MAX_VALUE).add(new BigDecimal(Math.ulp(Double.MAX_VALUE)).multiply(HALF)).toString());
737     }
738 
testStrictness()739     private static void testStrictness() {
740         final double expected = 0x0.0000008000000p-1022;
741 //        final double expected = 0x0.0000008000001p-1022;
742         boolean failed = false;
743         double conversion = 0.0;
744         double sum = 0.0; // Prevent conversion from being optimized away
745 
746         //2^-1047 + 2^-1075 rounds to 2^-1047
747         String decimal = "6.631236871469758276785396630275967243399099947355303144249971758736286630139265439618068200788048744105960420552601852889715006376325666595539603330361800519107591783233358492337208057849499360899425128640718856616503093444922854759159988160304439909868291973931426625698663157749836252274523485312442358651207051292453083278116143932569727918709786004497872322193856150225415211997283078496319412124640111777216148110752815101775295719811974338451936095907419622417538473679495148632480391435931767981122396703443803335529756003353209830071832230689201383015598792184172909927924176339315507402234836120730914783168400715462440053817592702766213559042115986763819482654128770595766806872783349146967171293949598850675682115696218943412532098591327667236328125E-316";
748 
749         for(int i = 0; i <= 12_000; i++) {
750             conversion = Double.parseDouble(decimal);
751             sum += conversion;
752             if (conversion != expected) {
753                 failed = true;
754                 System.out.printf("Iteration %d converts as %a%n",
755                                   i, conversion);
756             }
757         }
758 
759         System.out.println("Sum = "  + sum);
760         if (failed)
761             throw new RuntimeException("Inconsistent conversion");
762     }
763 
main(String[] args)764     public static void main(String[] args) throws Exception {
765         rudimentaryTest();
766 
767         testParsing(goodStrings, false);
768         testParsing(paddedGoodStrings, false);
769         testParsing(badStrings, true);
770         testParsing(paddedBadStrings, true);
771 
772         testRegex(goodStrings, false);
773         testRegex(paddedGoodStrings, false);
774         testRegex(badStrings, true);
775         testRegex(paddedBadStrings, true);
776 
777         testSubnormalPowers();
778         testPowers();
779         testStrictness();
780     }
781 }
782