Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8326627

Document Double/Float.valueOf(String) behavior for numeric strings with non-ASCII digits

XMLWordPrintable

    • b17
    • generic
    • generic
    • Verified

      ADDITIONAL SYSTEM INFORMATION :
      MacOS v14.2.1
      Oracle JDK v17.0.10
      Issue is also reproducible on other JDK versions

      A DESCRIPTION OF THE PROBLEM :
      Double.parseDouble() and Float.parseFloat() are throwing NumberFormatExceptions for fullwidth Unicode digits U+FF10 to U+FF19, see https://en.wikipedia.org/wiki/Halfwidth_and_Fullwidth_Forms_(Unicode_block)
      This behavior is unexpected, since parsing is successful and no NFEs are thrown for Integer.parseInt() and Long.parseLong().
      Also, Character.isDigit() returns true for fullwidth digits, so it is expected that Double and Float parsing should also be working.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Double.parseDouble("123"); // throws NFE
      Float.parseFloat("123"); // throws NFE
      See gist - https://gist.github.com/XDex/2e300189a07e8224524100f26b5f6b46

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Correct parsing and no NFEs thrown when parsing fullwidth digits:
      Double.parseDouble("123"); // returns 123.0
      Float.parseFloat("123"); // returns 123.0
      ACTUAL -
      Exception in thread "main" java.lang.NumberFormatException: For input string: "123"
      at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2054)
      at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
      at java.base/java.lang.Double.parseDouble(Double.java:651)

      ---------- BEGIN SOURCE ----------
      // See https://gist.github.com/XDex/2e300189a07e8224524100f26b5f6b46

      import org.apache.commons.lang3.math.NumberUtils;

      import java.text.NumberFormat;

      public class Main {
          private static final NumberFormat FORMAT = NumberFormat.getInstance();

          private static void tryParse(String s) {
              char c = s.charAt(0);
              System.out.println("Code point: " + (int) s.charAt(0));
              System.out.println("isDefined: " + Character.isDefined(c));
              System.out.println("isDigit: " + Character.isDigit(c));
              System.out.println("isParsable: " + NumberUtils.isParsable(s));
              System.out.println("parseInt: " + Integer.parseInt(s));
              System.out.println("parseLong: " + Long.parseLong(s));
              try {
                  System.out.println("parseDouble: " + Double.parseDouble(s));
              } catch (Exception e) {
                  System.out.println("Error: " + e);
              }
              try {
                  System.out.println("NumberFormat doubleValue: " + FORMAT.parse(s).doubleValue());
              } catch (Exception e) {
                  System.out.println("Error: " + e);
              }
              try {
                  System.out.println("parseFloat: " + Float.parseFloat(s));
              } catch (Exception e) {
                  System.out.println("Error: " + e);
              }
              try {
                  System.out.println("NumberFormat floatValue: " + FORMAT.parse(s).floatValue());
              } catch (Exception e) {
                  System.out.println("Error: " + e);
              }
          }

          public static void main(String[] args) {
              tryParse("123"); // OK
              tryParse("123"); // Throws NFEs for Float.parseFloat and Double.parseDouble
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      NumberFormat.getInstance().parse("123").doubleValue();
      NumberFormat.getInstance().parse("123").floatValue();

      FREQUENCY : always


            naoto Naoto Sato
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved: