1 /*
   2  * Copyright (c) 2001, 2011, 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 7021568 7039369
  27  * @summary Test for Double.parseDouble method and acceptance regex
  28  */
  29 
  30 import java.util.regex.*;
  31 import java.math.BigDecimal;
  32 
  33 public class ParseDouble {
  34 
  35     private static void check(String val, double expected) {
  36         double n = Double.parseDouble(val);
  37         if (n != expected)
  38             throw new RuntimeException("Double.parseDouble failed. String:" +
  39                                                 val + " Result:" + n);
  40     }
  41 
  42     private static void rudimentaryTest() {
  43         check(new String(""+Double.MIN_VALUE), Double.MIN_VALUE);
  44         check(new String(""+Double.MAX_VALUE), Double.MAX_VALUE);
  45 
  46         check("10",     (double)  10.0);
  47         check("10.0",   (double)  10.0);
  48         check("10.01",  (double)  10.01);
  49 
  50         check("-10",    (double) -10.0);
  51         check("-10.00", (double) -10.0);
  52         check("-10.01", (double) -10.01);
  53     }
  54 
  55 
  56     static  String badStrings[] = {
  57         "",
  58         "+",
  59         "-",
  60         "+e",
  61         "-e",
  62         "+e170",
  63         "-e170",
  64 
  65         // Make sure intermediate white space is not deleted.
  66         "1234   e10",
  67         "-1234   e10",
  68 
  69         // Control characters in the interior of a string are not legal
  70         "1\u0007e1",
  71         "1e\u00071",
  72 
  73         // NaN and infinity can't have trailing type suffices or exponents
  74         "NaNf",
  75         "NaNF",
  76         "NaNd",
  77         "NaND",
  78         "-NaNf",
  79         "-NaNF",
  80         "-NaNd",
  81         "-NaND",
  82         "+NaNf",
  83         "+NaNF",
  84         "+NaNd",
  85         "+NaND",
  86         "Infinityf",
  87         "InfinityF",
  88         "Infinityd",
  89         "InfinityD",
  90         "-Infinityf",
  91         "-InfinityF",
  92         "-Infinityd",
  93         "-InfinityD",
  94         "+Infinityf",
  95         "+InfinityF",
  96         "+Infinityd",
  97         "+InfinityD",
  98 
  99         "NaNe10",
 100         "-NaNe10",
 101         "+NaNe10",
 102         "Infinitye10",
 103         "-Infinitye10",
 104         "+Infinitye10",
 105 
 106         // Non-ASCII digits are not recognized
 107         "\u0661e\u0661", // 1e1 in Arabic-Indic digits
 108         "\u06F1e\u06F1", // 1e1 in Extended Arabic-Indic digits
 109         "\u0967e\u0967", // 1e1 in Devanagari digits
 110 
 111         // JCK test lex03592m3
 112         ".",
 113 
 114         // JCK test lex03592m4
 115         "e42",
 116 
 117         // JCK test lex03592m5
 118         ".e42",
 119 
 120         // JCK test lex03592m6
 121         "d",
 122 
 123         // JCK test lex03592m7
 124         ".d",
 125 
 126         // JCK test lex03592m8
 127         "e42d",
 128 
 129         // JCK test lex03592m9
 130         ".e42d",
 131 
 132         // JCK test lex03593m10
 133         "1A01.01125e-10d",
 134 
 135         // JCK test lex03593m11
 136         "2;3.01125e-10d",
 137 
 138         // JCK test lex03593m12
 139         "1_34.01125e-10d",
 140 
 141         // JCK test lex03593m14
 142         "202..01125e-10d",
 143 
 144         // JCK test lex03593m15
 145         "202,01125e-10d",
 146 
 147         // JCK test lex03593m16
 148         "202.03b4e-10d",
 149 
 150         // JCK test lex03593m18
 151         "202.06_3e-10d",
 152 
 153         // JCK test lex03593m20
 154         "202.01125e-f0d",
 155 
 156         // JCK test lex03593m21
 157         "202.01125e_3d",
 158 
 159         // JCK test lex03593m22
 160         "202.01125e -5d",
 161 
 162         // JCK test lex03593m24
 163         "202.01125e-10r",
 164 
 165         // JCK test lex03593m25
 166         "202.01125e-10ff",
 167 
 168         // JCK test lex03593m26
 169         "1234L.01",
 170 
 171         // JCK test lex03593m27
 172         "12ee-2",
 173 
 174         // JCK test lex03593m28
 175         "12e-2.2.2",
 176 
 177         // JCK test lex03593m29
 178         "12.01e+",
 179 
 180         // JCK test lex03593m30
 181         "12.01E",
 182 
 183         // Bad hexadecimal-style strings
 184 
 185         // Two leading zeros
 186         "00x1.0p1",
 187 
 188         // Must have hex specifier
 189         "1.0p1",
 190         "00010p1",
 191         "deadbeefp1",
 192 
 193         // Need an explicit fully-formed exponent
 194         "0x1.0p",
 195         "0x1.0",
 196 
 197         // Exponent must be in decimal
 198         "0x1.0pa",
 199         "0x1.0pf",
 200 
 201         // Exponent separated by "p"
 202         "0x1.0e22",
 203         "0x1.0e22",
 204 
 205         // Need a signifcand
 206         "0xp22"
 207     };
 208 
 209     static String goodStrings[] = {
 210         "NaN",
 211         "+NaN",
 212         "-NaN",
 213         "Infinity",
 214         "+Infinity",
 215         "-Infinity",
 216         "1.1e-23f",
 217         ".1e-23f",
 218         "1e-23",
 219         "1f",
 220         "0",
 221         "-0",
 222         "+0",
 223         "00",
 224         "00",
 225         "-00",
 226         "+00",
 227         "0000000000",
 228         "-0000000000",
 229         "+0000000000",
 230         "1",
 231         "2",
 232         "1234",
 233         "-1234",
 234         "+1234",
 235         "2147483647",   // Integer.MAX_VALUE
 236         "2147483648",
 237         "-2147483648",  // Integer.MIN_VALUE
 238         "-2147483649",
 239 
 240         "16777215",
 241         "16777216",     // 2^24
 242         "16777217",
 243 
 244         "-16777215",
 245         "-16777216",    // -2^24
 246         "-16777217",
 247 
 248         "9007199254740991",
 249         "9007199254740992",     // 2^53
 250         "9007199254740993",
 251 
 252         "-9007199254740991",
 253         "-9007199254740992",    // -2^53
 254         "-9007199254740993",
 255 
 256         "9223372036854775807",
 257         "9223372036854775808",  // Long.MAX_VALUE
 258         "9223372036854775809",
 259 
 260         "-9223372036854775808",
 261         "-9223372036854775809", // Long.MIN_VALUE
 262         "-9223372036854775810",
 263 
 264         // Culled from JCK test lex03591m1
 265         "54.07140d",
 266         "7.01e-324d",
 267         "2147483647.01d",
 268         "1.2147483647f",
 269         "000000000000000000000000001.F",
 270         "1.00000000000000000000000000e-2F",
 271 
 272         // Culled from JCK test lex03592m2
 273         "2.",
 274         ".0909",
 275         "122112217090.0",
 276         "7090e-5",
 277         "2.E-20",
 278         ".0909e42",
 279         "122112217090.0E+100",
 280         "7090f",
 281         "2.F",
 282         ".0909d",
 283         "122112217090.0D",
 284         "7090e-5f",
 285         "2.E-20F",
 286         ".0909e42d",
 287         "122112217090.0E+100D",
 288 
 289         // Culled from JCK test lex03594m31 -- unicode escapes
 290         "\u0035\u0031\u0034\u0039\u0032\u0033\u0036\u0037\u0038\u0030.1102E-209D",
 291         "1290873\u002E12301e100",
 292         "1.1E-10\u0066",
 293 
 294         // Culled from JCK test lex03595m1
 295         "0.0E-10",
 296         "1E10",
 297 
 298         // Culled from JCK test lex03691m1
 299         "0.f",
 300         "1f",
 301         "0.F",
 302         "1F",
 303         "0.12d",
 304         "1e-0d",
 305         "12.e+1D",
 306         "0e-0D",
 307         "12.e+01",
 308         "1e-01",
 309 
 310         // Good hex strings
 311         // Vary capitalization of separators.
 312 
 313         "0x1p1",
 314         "0X1p1",
 315         "0x1P1",
 316         "0X1P1",
 317         "0x1p1f",
 318         "0X1p1f",
 319         "0x1P1f",
 320         "0X1P1f",
 321         "0x1p1F",
 322         "0X1p1F",
 323         "0x1P1F",
 324         "0X1P1F",
 325         "0x1p1d",
 326         "0X1p1d",
 327         "0x1P1d",
 328         "0X1P1d",
 329         "0x1p1D",
 330         "0X1p1D",
 331         "0x1P1D",
 332         "0X1P1D",
 333 
 334         "-0x1p1",
 335         "-0X1p1",
 336         "-0x1P1",
 337         "-0X1P1",
 338         "-0x1p1f",
 339         "-0X1p1f",
 340         "-0x1P1f",
 341         "-0X1P1f",
 342         "-0x1p1F",
 343         "-0X1p1F",
 344         "-0x1P1F",
 345         "-0X1P1F",
 346         "-0x1p1d",
 347         "-0X1p1d",
 348         "-0x1P1d",
 349         "-0X1P1d",
 350         "-0x1p1D",
 351         "-0X1p1D",
 352         "-0x1P1D",
 353         "-0X1P1D",
 354 
 355         "0x1p-1",
 356         "0X1p-1",
 357         "0x1P-1",
 358         "0X1P-1",
 359         "0x1p-1f",
 360         "0X1p-1f",
 361         "0x1P-1f",
 362         "0X1P-1f",
 363         "0x1p-1F",
 364         "0X1p-1F",
 365         "0x1P-1F",
 366         "0X1P-1F",
 367         "0x1p-1d",
 368         "0X1p-1d",
 369         "0x1P-1d",
 370         "0X1P-1d",
 371         "0x1p-1D",
 372         "0X1p-1D",
 373         "0x1P-1D",
 374         "0X1P-1D",
 375 
 376         "-0x1p-1",
 377         "-0X1p-1",
 378         "-0x1P-1",
 379         "-0X1P-1",
 380         "-0x1p-1f",
 381         "-0X1p-1f",
 382         "-0x1P-1f",
 383         "-0X1P-1f",
 384         "-0x1p-1F",
 385         "-0X1p-1F",
 386         "-0x1P-1F",
 387         "-0X1P-1F",
 388         "-0x1p-1d",
 389         "-0X1p-1d",
 390         "-0x1P-1d",
 391         "-0X1P-1d",
 392         "-0x1p-1D",
 393         "-0X1p-1D",
 394         "-0x1P-1D",
 395         "-0X1P-1D",
 396 
 397 
 398         // Try different significand combinations
 399         "0xap1",
 400         "0xbp1",
 401         "0xcp1",
 402         "0xdp1",
 403         "0xep1",
 404         "0xfp1",
 405 
 406         "0x1p1",
 407         "0x.1p1",
 408         "0x1.1p1",
 409 
 410         "0x001p23",
 411         "0x00.1p1",
 412         "0x001.1p1",
 413 
 414         "0x100p1",
 415         "0x.100p1",
 416         "0x1.100p1",
 417 
 418         "0x00100p1",
 419         "0x00.100p1",
 420         "0x001.100p1",
 421 
 422         // Limits
 423 
 424         "1.7976931348623157E308",     // Double.MAX_VALUE
 425         "4.9e-324",                   // Double.MIN_VALUE
 426         "2.2250738585072014e-308",    // Double.MIN_NORMAL
 427 
 428         "2.2250738585072012e-308",    // near Double.MIN_NORMAL
 429     };
 430 
 431     static String paddedBadStrings[];
 432     static String paddedGoodStrings[];
 433     static {
 434         String pad = " \t\n\r\f\u0001\u000b\u001f";
 435         paddedBadStrings = new String[badStrings.length];
 436         for(int i = 0 ; i <  badStrings.length; i++)
 437             paddedBadStrings[i] = pad + badStrings[i] + pad;
 438 
 439         paddedGoodStrings = new String[goodStrings.length];
 440         for(int i = 0 ; i <  goodStrings.length; i++)
 441             paddedGoodStrings[i] = pad + goodStrings[i] + pad;
 442 
 443     }
 444 
 445 
 446     /*
 447      * Throws an exception if <code>Input</code> is
 448      * <code>exceptionalInput</code> and {@link Double.parseDouble
 449      * parseDouble} does <em>not</em> throw an exception or if
 450      * <code>Input</code> is not <code>exceptionalInput</code> and
 451      * <code>parseDouble</code> throws an exception.  This method does
 452      * not attempt to test whether the string is converted to the
 453      * proper value; just whether the input is accepted appropriately
 454      * or not.
 455      */
 456     private static void testParsing(String [] input,
 457                                     boolean exceptionalInput) {
 458         for(int i = 0; i < input.length; i++) {
 459             double d;
 460 
 461             try {
 462                 d = Double.parseDouble(input[i]);
 463             }
 464             catch (NumberFormatException e) {
 465                 if (! exceptionalInput) {
 466                     throw new RuntimeException("Double.parseDouble rejected " +
 467                                                "good string `" + input[i] +
 468                                                "'.");
 469                 }
 470                 break;
 471             }
 472             if (exceptionalInput) {
 473                 throw new RuntimeException("Double.parseDouble accepted " +
 474                                            "bad string `" + input[i] +
 475                                            "'.");
 476             }
 477         }
 478     }
 479 
 480     /*
 481      * Throws an exception if <code>Input</code> is
 482      * <code>exceptionalInput</code> and the regular expression
 483      * matches one of the strings or if <code>Input</code> is not
 484      * <code>exceptionalInput</code> and the regular expression fails
 485      * to match an input string.
 486      */
 487     private static void testRegex(String [] input, boolean exceptionalInput) {
 488         /*
 489          * The regex below is taken from the JavaDoc for
 490          * Double.valueOf.
 491          */
 492 
 493         final String Digits     = "(\\p{Digit}+)";
 494         final String HexDigits  = "(\\p{XDigit}+)";
 495         // an exponent is 'e' or 'E' followed by an optionally
 496         // signed decimal integer.
 497         final String Exp        = "[eE][+-]?"+Digits;
 498         final String fpRegex    =
 499             ("[\\x00-\\x20]*"+  // Optional leading "whitespace"
 500              "[+-]?(" + // Optional sign character
 501              "NaN|" +           // "NaN" string
 502              "Infinity|" +      // "Infinity" string
 503 
 504              // A floating-point string representing a finite positive
 505              // number without a leading sign has at most five basic pieces:
 506              // Digits . Digits ExponentPart FloatTypeSuffix
 507              //
 508              // Since this method allows integer-only strings as input
 509              // in addition to strings of floating-point literals, the
 510              // two sub-patterns below are simplifications of the grammar
 511              // productions from the Java Language Specification, 2nd
 512              // edition, section 3.10.2.
 513 
 514 
 515              // A decimal floating-point string representing a finite positive
 516              // number without a leading sign has at most five basic pieces:
 517              // Digits . Digits ExponentPart FloatTypeSuffix
 518              //
 519              // Since this method allows integer-only strings as input
 520              // in addition to strings of floating-point literals, the
 521              // two sub-patterns below are simplifications of the grammar
 522              // productions from the Java Language Specification, 2nd
 523              // edition, section 3.10.2.
 524 
 525              // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
 526              "(((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+
 527 
 528              // . Digits ExponentPart_opt FloatTypeSuffix_opt
 529              "(\\.("+Digits+")("+Exp+")?))|"+
 530 
 531             // Hexadecimal strings
 532             "((" +
 533              // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
 534              "(0[xX]" + HexDigits + "(\\.)?)|" +
 535 
 536              // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
 537              "(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" +
 538 
 539              ")[pP][+-]?" + Digits + "))" +
 540              "[fFdD]?))" +
 541              "[\\x00-\\x20]*");// Optional trailing "whitespace"
 542         Pattern fpPattern = Pattern.compile(fpRegex);
 543 
 544         for(int i = 0; i < input.length; i++) {
 545              Matcher m = fpPattern.matcher(input[i]);
 546              if (m.matches() != ! exceptionalInput) {
 547                  throw new RuntimeException("Regular expression " +
 548                                             (exceptionalInput?
 549                                              "accepted bad":
 550                                              "rejected good") +
 551                                             " string `" +
 552                                             input[i] + "'.");
 553              }
 554         }
 555 
 556     }
 557 
 558     /**
 559      * For each subnormal power of two, test at boundaries of
 560      * region that should convert to that value.
 561      */
 562     private static void testSubnormalPowers() {
 563         BigDecimal TWO = BigDecimal.valueOf(2);
 564         // An ulp is the same for all subnormal values
 565         BigDecimal ulp_BD = new BigDecimal(Double.MIN_VALUE);
 566 
 567         // Test subnormal powers of two
 568         for(int i = -1074; i <= -1022; i++) {
 569             double d = Math.scalb(1.0, i);
 570 
 571             /*
 572              * The region [d - ulp/2, d + ulp/2] should round to d.
 573              */
 574             BigDecimal d_BD = new BigDecimal(d);
 575 
 576             BigDecimal lowerBound = d_BD.subtract(ulp_BD.divide(TWO));
 577             BigDecimal upperBound = d_BD.add(ulp_BD.divide(TWO));
 578 
 579             double convertedLowerBound = Double.parseDouble(lowerBound.toString());
 580             double convertedUpperBound = Double.parseDouble(upperBound.toString());
 581         }
 582     }
 583 
 584 
 585     private static void testStrictness() {
 586         final double expected = 0x0.0000008000001p-1022;
 587         boolean failed = false;
 588         double conversion = 0.0;
 589         double sum = 0.0; // Prevent conversion from being optimized away
 590 
 591         //2^-1047 + 2^-1075
 592         String decimal = "6.631236871469758276785396630275967243399099947355303144249971758736286630139265439618068200788048744105960420552601852889715006376325666595539603330361800519107591783233358492337208057849499360899425128640718856616503093444922854759159988160304439909868291973931426625698663157749836252274523485312442358651207051292453083278116143932569727918709786004497872322193856150225415211997283078496319412124640111777216148110752815101775295719811974338451936095907419622417538473679495148632480391435931767981122396703443803335529756003353209830071832230689201383015598792184172909927924176339315507402234836120730914783168400715462440053817592702766213559042115986763819482654128770595766806872783349146967171293949598850675682115696218943412532098591327667236328125E-316";
 593 
 594         for(int i = 0; i <= 12_000; i++) {
 595             conversion = Double.parseDouble(decimal);
 596             sum += conversion;
 597             if (conversion != expected) {
 598                 failed = true;
 599                 System.out.printf("Iteration %d converts as %a%n",
 600                                   i, conversion);
 601             }
 602         }
 603 
 604         System.out.println("Sum = "  + sum);
 605         if (failed)
 606             throw new RuntimeException("Inconsistent conversion");
 607     }
 608 
 609     public static void main(String[] args) throws Exception {
 610         rudimentaryTest();
 611 
 612         testParsing(goodStrings, false);
 613         testParsing(paddedGoodStrings, false);
 614         testParsing(badStrings, true);
 615         testParsing(paddedBadStrings, true);
 616 
 617         testRegex(goodStrings, false);
 618         testRegex(paddedGoodStrings, false);
 619         testRegex(badStrings, true);
 620         testRegex(paddedBadStrings, true);
 621 
 622         testSubnormalPowers();
 623         testStrictness();
 624     }
 625 }