1 /*
  2  * Copyright (c) 2001, 2013, 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 import java.math.BigDecimal;
 31 import java.math.BigInteger;
 32 import java.util.regex.*;
 33 
 34 public class ParseDouble {
 35 
 36     private static final BigDecimal HALF = BigDecimal.valueOf(0.5);
 37 
 38     private static void fail(String val, double n) {
 39         throw new RuntimeException("Double.parseDouble failed. String:" +
 40                                                 val + " Result:" + n);
 41     }
 42 
 43     private static void check(String val) {
 44         double n = Double.parseDouble(val);
 45         boolean isNegativeN = n < 0 || n == 0 && 1/n < 0;
 46         double na = Math.abs(n);
 47         String s = val.trim().toLowerCase();
 48         switch (s.charAt(s.length() - 1)) {
 49             case 'd':
 50             case 'f':
 51                 s = s.substring(0, s.length() - 1);
 52                 break;
 53         }
 54         boolean isNegative = false;
 55         if (s.charAt(0) == '+') {
 56             s = s.substring(1);
 57         } else if (s.charAt(0) == '-') {
 58             s = s.substring(1);
 59             isNegative = true;
 60         }
 61         if (s.equals("nan")) {
 62             if (!Double.isNaN(n)) {
 63                 fail(val, n);
 64             }
 65             return;
 66         }
 67         if (Double.isNaN(n)) {
 68             fail(val, n);
 69         }
 70         if (isNegativeN != isNegative)
 71             fail(val, n);
 72         if (s.equals("infinity")) {
 73             if (na != Double.POSITIVE_INFINITY) {
 74                 fail(val, n);
 75             }
 76             return;
 77         }
 78         BigDecimal bd;
 79         if (s.startsWith("0x")) {
 80             s = s.substring(2);
 81             int indP = s.indexOf('p');
 82             long exp = Long.parseLong(s.substring(indP + 1));
 83             int indD = s.indexOf('.');
 84             String significand;
 85             if (indD >= 0) {
 86                 significand = s.substring(0, indD) + s.substring(indD + 1, indP);
 87                 exp -= 4*(indP - indD - 1);
 88             } else {
 89                 significand = s.substring(0, indP);
 90             }
 91             bd = new BigDecimal(new BigInteger(significand, 16));
 92             if (exp >= 0) {
 93                 bd = bd.multiply(BigDecimal.valueOf(2).pow((int)exp));
 94             } else {
 95                 bd = bd.divide(BigDecimal.valueOf(2).pow((int)-exp));
 96             }
 97         } else {
 98             bd = new BigDecimal(s);
 99         }
100         BigDecimal l, u;
101         if (Double.isInfinite(na)) {
102             l = new BigDecimal(Double.MAX_VALUE).add(new BigDecimal(Math.ulp(Double.MAX_VALUE)).multiply(HALF));
103             u = null;
104         } else {
105             l = new BigDecimal(na).subtract(new BigDecimal(Math.ulp(Math.nextUp(-na))).multiply(HALF));
106             u = new BigDecimal(na).add(new BigDecimal(Math.ulp(n)).multiply(HALF));
107         }
108         int cmpL = bd.compareTo(l);
109         int cmpU = u != null ? bd.compareTo(u) : -1;
110         if ((Double.doubleToLongBits(n) & 1) != 0) {
111             if (cmpL <= 0 || cmpU >= 0) {
112                 fail(val, n);
113             }
114         } else {
115             if (cmpL < 0 || cmpU > 0) {
116                 fail(val, n);
117             }
118         }
119     }
120 
121     private static void check(String val, double expected) {
122         double n = Double.parseDouble(val);
123         if (n != expected)
124             fail(val, n);
125         check(val);
126     }
127 
128     private static void rudimentaryTest() {
129         check(new String(""+Double.MIN_VALUE), Double.MIN_VALUE);
130         check(new String(""+Double.MAX_VALUE), Double.MAX_VALUE);
131 
132         check("10",     (double)  10.0);
133         check("10.0",   (double)  10.0);
134         check("10.01",  (double)  10.01);
135 
136         check("-10",    (double) -10.0);
137         check("-10.00", (double) -10.0);
138         check("-10.01", (double) -10.01);
139     }
140 
141 
142     static  String badStrings[] = {
143         "",
144         "+",
145         "-",
146         "+e",
147         "-e",
148         "+e170",
149         "-e170",
150 
151         // Make sure intermediate white space is not deleted.
152         "1234   e10",
153         "-1234   e10",
154 
155         // Control characters in the interior of a string are not legal
156         "1\u0007e1",
157         "1e\u00071",
158 
159         // NaN and infinity can't have trailing type suffices or exponents
160         "NaNf",
161         "NaNF",
162         "NaNd",
163         "NaND",
164         "-NaNf",
165         "-NaNF",
166         "-NaNd",
167         "-NaND",
168         "+NaNf",
169         "+NaNF",
170         "+NaNd",
171         "+NaND",
172         "Infinityf",
173         "InfinityF",
174         "Infinityd",
175         "InfinityD",
176         "-Infinityf",
177         "-InfinityF",
178         "-Infinityd",
179         "-InfinityD",
180         "+Infinityf",
181         "+InfinityF",
182         "+Infinityd",
183         "+InfinityD",
184 
185         "NaNe10",
186         "-NaNe10",
187         "+NaNe10",
188         "Infinitye10",
189         "-Infinitye10",
190         "+Infinitye10",
191 
192         // Non-ASCII digits are not recognized
193         "\u0661e\u0661", // 1e1 in Arabic-Indic digits
194         "\u06F1e\u06F1", // 1e1 in Extended Arabic-Indic digits
195         "\u0967e\u0967", // 1e1 in Devanagari digits
196 
197         // JCK test lex03592m3
198         ".",
199 
200         // JCK test lex03592m4
201         "e42",
202 
203         // JCK test lex03592m5
204         ".e42",
205 
206         // JCK test lex03592m6
207         "d",
208 
209         // JCK test lex03592m7
210         ".d",
211 
212         // JCK test lex03592m8
213         "e42d",
214 
215         // JCK test lex03592m9
216         ".e42d",
217 
218         // JCK test lex03593m10
219         "1A01.01125e-10d",
220 
221         // JCK test lex03593m11
222         "2;3.01125e-10d",
223 
224         // JCK test lex03593m12
225         "1_34.01125e-10d",
226 
227         // JCK test lex03593m14
228         "202..01125e-10d",
229 
230         // JCK test lex03593m15
231         "202,01125e-10d",
232 
233         // JCK test lex03593m16
234         "202.03b4e-10d",
235 
236         // JCK test lex03593m18
237         "202.06_3e-10d",
238 
239         // JCK test lex03593m20
240         "202.01125e-f0d",
241 
242         // JCK test lex03593m21
243         "202.01125e_3d",
244 
245         // JCK test lex03593m22
246         "202.01125e -5d",
247 
248         // JCK test lex03593m24
249         "202.01125e-10r",
250 
251         // JCK test lex03593m25
252         "202.01125e-10ff",
253 
254         // JCK test lex03593m26
255         "1234L.01",
256 
257         // JCK test lex03593m27
258         "12ee-2",
259 
260         // JCK test lex03593m28
261         "12e-2.2.2",
262 
263         // JCK test lex03593m29
264         "12.01e+",
265 
266         // JCK test lex03593m30
267         "12.01E",
268 
269         // Bad hexadecimal-style strings
270 
271         // Two leading zeros
272         "00x1.0p1",
273 
274         // Must have hex specifier
275         "1.0p1",
276         "00010p1",
277         "deadbeefp1",
278 
279         // Need an explicit fully-formed exponent
280         "0x1.0p",
281         "0x1.0",
282 
283         // Exponent must be in decimal
284         "0x1.0pa",
285         "0x1.0pf",
286 
287         // Exponent separated by "p"
288         "0x1.0e22",
289         "0x1.0e22",
290 
291         // Need a signifcand
292         "0xp22"
293     };
294 
295     static String goodStrings[] = {
296         "NaN",
297         "+NaN",
298         "-NaN",
299         "Infinity",
300         "+Infinity",
301         "-Infinity",
302         "1.1e-23f",
303         ".1e-23f",
304         "1e-23",
305         "1f",
306         "0",
307         "-0",
308         "+0",
309         "00",
310         "00",
311         "-00",
312         "+00",
313         "0000000000",
314         "-0000000000",
315         "+0000000000",
316         "1",
317         "2",
318         "1234",
319         "-1234",
320         "+1234",
321         "2147483647",   // Integer.MAX_VALUE
322         "2147483648",
323         "-2147483648",  // Integer.MIN_VALUE
324         "-2147483649",
325 
326         "16777215",
327         "16777216",     // 2^24
328         "16777217",
329 
330         "-16777215",
331         "-16777216",    // -2^24
332         "-16777217",
333 
334         "9007199254740991",
335         "9007199254740992",     // 2^53
336         "9007199254740993",
337 
338         "-9007199254740991",
339         "-9007199254740992",    // -2^53
340         "-9007199254740993",
341 
342         "9223372036854775807",
343         "9223372036854775808",  // Long.MAX_VALUE
344         "9223372036854775809",
345 
346         "-9223372036854775808",
347         "-9223372036854775809", // Long.MIN_VALUE
348         "-9223372036854775810",
349 
350         // Culled from JCK test lex03591m1
351         "54.07140d",
352         "7.01e-324d",
353         "2147483647.01d",
354         "1.2147483647f",
355         "000000000000000000000000001.F",
356         "1.00000000000000000000000000e-2F",
357 
358         // Culled from JCK test lex03592m2
359         "2.",
360         ".0909",
361         "122112217090.0",
362         "7090e-5",
363         "2.E-20",
364         ".0909e42",
365         "122112217090.0E+100",
366         "7090f",
367         "2.F",
368         ".0909d",
369         "122112217090.0D",
370         "7090e-5f",
371         "2.E-20F",
372         ".0909e42d",
373         "122112217090.0E+100D",
374 
375         // Culled from JCK test lex03594m31 -- unicode escapes
376         "\u0035\u0031\u0034\u0039\u0032\u0033\u0036\u0037\u0038\u0030.1102E-209D",
377         "1290873\u002E12301e100",
378         "1.1E-10\u0066",
379 
380         // Culled from JCK test lex03595m1
381         "0.0E-10",
382         "1E10",
383 
384         // Culled from JCK test lex03691m1
385         "0.f",
386         "1f",
387         "0.F",
388         "1F",
389         "0.12d",
390         "1e-0d",
391         "12.e+1D",
392         "0e-0D",
393         "12.e+01",
394         "1e-01",
395 
396         // Good hex strings
397         // Vary capitalization of separators.
398 
399         "0x1p1",
400         "0X1p1",
401         "0x1P1",
402         "0X1P1",
403         "0x1p1f",
404         "0X1p1f",
405         "0x1P1f",
406         "0X1P1f",
407         "0x1p1F",
408         "0X1p1F",
409         "0x1P1F",
410         "0X1P1F",
411         "0x1p1d",
412         "0X1p1d",
413         "0x1P1d",
414         "0X1P1d",
415         "0x1p1D",
416         "0X1p1D",
417         "0x1P1D",
418         "0X1P1D",
419 
420         "-0x1p1",
421         "-0X1p1",
422         "-0x1P1",
423         "-0X1P1",
424         "-0x1p1f",
425         "-0X1p1f",
426         "-0x1P1f",
427         "-0X1P1f",
428         "-0x1p1F",
429         "-0X1p1F",
430         "-0x1P1F",
431         "-0X1P1F",
432         "-0x1p1d",
433         "-0X1p1d",
434         "-0x1P1d",
435         "-0X1P1d",
436         "-0x1p1D",
437         "-0X1p1D",
438         "-0x1P1D",
439         "-0X1P1D",
440 
441         "0x1p-1",
442         "0X1p-1",
443         "0x1P-1",
444         "0X1P-1",
445         "0x1p-1f",
446         "0X1p-1f",
447         "0x1P-1f",
448         "0X1P-1f",
449         "0x1p-1F",
450         "0X1p-1F",
451         "0x1P-1F",
452         "0X1P-1F",
453         "0x1p-1d",
454         "0X1p-1d",
455         "0x1P-1d",
456         "0X1P-1d",
457         "0x1p-1D",
458         "0X1p-1D",
459         "0x1P-1D",
460         "0X1P-1D",
461 
462         "-0x1p-1",
463         "-0X1p-1",
464         "-0x1P-1",
465         "-0X1P-1",
466         "-0x1p-1f",
467         "-0X1p-1f",
468         "-0x1P-1f",
469         "-0X1P-1f",
470         "-0x1p-1F",
471         "-0X1p-1F",
472         "-0x1P-1F",
473         "-0X1P-1F",
474         "-0x1p-1d",
475         "-0X1p-1d",
476         "-0x1P-1d",
477         "-0X1P-1d",
478         "-0x1p-1D",
479         "-0X1p-1D",
480         "-0x1P-1D",
481         "-0X1P-1D",
482 
483 
484         // Try different significand combinations
485         "0xap1",
486         "0xbp1",
487         "0xcp1",
488         "0xdp1",
489         "0xep1",
490         "0xfp1",
491 
492         "0x1p1",
493         "0x.1p1",
494         "0x1.1p1",
495 
496         "0x001p23",
497         "0x00.1p1",
498         "0x001.1p1",
499 
500         "0x100p1",
501         "0x.100p1",
502         "0x1.100p1",
503 
504         "0x00100p1",
505         "0x00.100p1",
506         "0x001.100p1",
507 
508         // Limits
509 
510         "1.7976931348623157E308",     // Double.MAX_VALUE
511         "4.9e-324",                   // Double.MIN_VALUE
512         "2.2250738585072014e-308",    // Double.MIN_NORMAL
513 
514         "2.2250738585072012e-308",    // near Double.MIN_NORMAL
515 
516         "1.7976931348623158e+308",    // near MAX_VALUE + ulp(MAX_VALUE)/2
517         "1.7976931348623159e+308",    // near MAX_VALUE + ulp(MAX_VALUE)
518 
519         "2.4703282292062329e-324",    // above MIN_VALUE/2
520         "2.4703282292062327e-324",    // MIN_VALUE/2
521         "2.4703282292062325e-324",    // below MIN_VALUE/2
522 
523         // 1e308 with leading zeros
524 
525         "0.0000000000001e321",
526         "00.000000000000000001e326",
527         "00000.000000000000000001e326",
528         "000.0000000000000000001e327",
529         "0.00000000000000000001e328",
530     };
531 
532     static String paddedBadStrings[];
533     static String paddedGoodStrings[];
534     static {
535         String pad = " \t\n\r\f\u0001\u000b\u001f";
536         paddedBadStrings = new String[badStrings.length];
537         for(int i = 0 ; i <  badStrings.length; i++)
538             paddedBadStrings[i] = pad + badStrings[i] + pad;
539 
540         paddedGoodStrings = new String[goodStrings.length];
541         for(int i = 0 ; i <  goodStrings.length; i++)
542             paddedGoodStrings[i] = pad + goodStrings[i] + pad;
543 
544     }
545 
546 
547     /*
548      * Throws an exception if <code>Input</code> is
549      * <code>exceptionalInput</code> and {@link Double.parseDouble
550      * parseDouble} does <em>not</em> throw an exception or if
551      * <code>Input</code> is not <code>exceptionalInput</code> and
552      * <code>parseDouble</code> throws an exception.  This method does
553      * not attempt to test whether the string is converted to the
554      * proper value; just whether the input is accepted appropriately
555      * or not.
556      */
557     private static void testParsing(String [] input,
558                                     boolean exceptionalInput) {
559         for(int i = 0; i < input.length; i++) {
560             double d;
561 
562             try {
563                 d = Double.parseDouble(input[i]);
564                 check(input[i]);
565             }
566             catch (NumberFormatException e) {
567                 if (! exceptionalInput) {
568                     throw new RuntimeException("Double.parseDouble rejected " +
569                                                "good string `" + input[i] +
570                                                "'.");
571                 }
572                 break;
573             }
574             if (exceptionalInput) {
575                 throw new RuntimeException("Double.parseDouble accepted " +
576                                            "bad string `" + input[i] +
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      */
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      */
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      */
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 
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 
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 }