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 }