BigDecimal具有NextBigDecimal行为

时间:2018-10-29 06:10:31

标签: java bigdecimal

以下代码完全符合预期:

import java.math.BigDecimal;
import java.util.Scanner;

public class Test2 {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        BigDecimal number = new BigDecimal("0");
        System.out.print("Enter a number: ");
        try {
            number = new BigDecimal(input.next());
        }
        catch(Exception e) {
            System.out.println("Not a number.");
        }
        System.out.println(number);
    }
}
  • 正确:如果我输入字符串,它将失败。
  • 正确:如果我输入1,1,它将失败。
  • 正确:如果我键入1,它会成功。
  • 正确:如果我输入1.1,就会成功

如果我按如下所示删除try catch块并将其替换为while循环,则它不会执行预期的操作:

import java.math.BigDecimal;
import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Enter a number: ");
        while (!input.hasNextBigDecimal()) {
            System.out.print("Not a number, try again: ");
            input.next();
        }
        BigDecimal number = input.nextBigDecimal();
        System.out.println(number);
    }
}
  • 正确:如果输入字符串,它将失败。
  • 不正确:如果键入1.1,它将失败。
  • 正确:如果我键入1,它会成功。
  • 不正确:如果我输入1,1,则成功

这是我运行时的输出:java Test

C:\>java Test
Enter a number: 1,1
1.1

为什么会接受逗号,但打印句号?

如果我运行以下代码,它将输出:en_ZA

import java.util.Locale;

public class Test3 {
    public static void main(String[] args) {
        System.out.println(Locale.getDefault());
    }
}

如以下链接所示,我的语言环境的小数点分隔符是句点:

http://www.localeplanet.com/java/en-ZA/index.html

请告知我要去哪里了。

编辑:

在进一步调查中,我发现以下内容: https://www.sadev.co.za/content/how-correctly-format-currency-south-africa

因此,语言环境在技术上确实使用逗号。介意:)

1 个答案:

答案 0 :(得分:2)

Scanner.hasNextBigDecimal()使用默认语言环境的分组和小数点分隔符(在您的语言环境中似乎是“。”用于分组,而“,”则是十进制)来验证下一个标记是否与decimalpattern相匹配:

...
DecimalFormat df =
    (DecimalFormat)NumberFormat.getNumberInstance(locale);
DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(locale);

// These must be literalized to avoid collision with regex
// metacharacters such as dot or parenthesis
groupSeparator =   "\\" + dfs.getGroupingSeparator();
decimalSeparator = "\\" + dfs.getDecimalSeparator();
...

这段代码来自Scanner类,并在初始化scanner实例时执行。然后在调用groupSeparator时使用decimalSeparatorScanner.hasNextBigDecimal()来检查下一个标记是否与十进制格式匹配。


new BigDecimal(String)直接使用'。作为小数点分隔符。


因此,如果您想使用Scanner.hasNextBigDecimal()和'。作为用户输入的小数点分隔符,则应使用Scanner的{​​{1}}方法。您的代码保存如下:

useLocale(Locale)

  

该程序接受逗号作为有效输入,然后打印句点   作为小数点。

再次Scanner input = new Scanner(System.in); input.useLocale(Locale.ENGLISH); System.out.print("Enter a number: "); while (!input.hasNextBigDecimal()) { System.out.print("Not a number, try again: "); input.next(); } BigDecimal number = input.nextBigDecimal(); System.out.println(number); 的{​​{1}}方法将所有Scanner替换为nextBigDecimal(),将groupSeparator替换为"",然后调用'new BigDecimal (串)'。 decimalSeparator类的代码段是:

"."

这就是为什么它接受Scanner并打印private String processFloatToken(String token) { String result = token.replaceAll(groupSeparator, ""); if (!decimalSeparator.equals("\\.")) result = result.replaceAll(decimalSeparator, "."); 的原因。