BigDecimal 具有 NextBigDecimal 行为
BigDecimal hasNextBigDecimal behavior
以下代码完全符合预期:
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测试
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());
}
}
正如您在下面的 link 中看到的,我的语言环境的小数点分隔符是句点:
http://www.localeplanet.com/java/en-ZA/index.html
请指教我哪里错了。
编辑:
经过进一步调查,我发现了以下内容:
https://www.sadev.co.za/content/how-correctly-format-currency-south-africa
所以语言环境在技术上确实使用了逗号。脑洞大开:)
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
class 并在初始化您的 scanner
实例时执行。然后在调用 Scanner.hasNextBigDecimal()
时使用 groupSeparator
和 decimalSeparator
来检查下一个标记是否与十进制格式匹配。
new BigDecimal(String)
直接使用'.'作为小数点分隔符。
因此,如果您想使用 Scanner.hasNextBigDecimal()
和“.”作为用户输入的小数点分隔符,那么你应该使用 Scanner
s 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);
the program accepts a comma as valid input, but then prints a period
as the decimal point.
再次在 Scanner
的 nextBigDecimal()
方法中将所有 groupSeparator
替换为 ""
并将 decimalSeparator
替换为 "."
=49=]。来自 Scanner
class 的一段代码是:
private String processFloatToken(String token) {
String result = token.replaceAll(groupSeparator, "");
if (!decimalSeparator.equals("\."))
result = result.replaceAll(decimalSeparator, ".");
这就是它接受 ,
并打印 .
的原因。
以下代码完全符合预期:
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测试
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());
}
}
正如您在下面的 link 中看到的,我的语言环境的小数点分隔符是句点:
http://www.localeplanet.com/java/en-ZA/index.html
请指教我哪里错了。
编辑:
经过进一步调查,我发现了以下内容: https://www.sadev.co.za/content/how-correctly-format-currency-south-africa
所以语言环境在技术上确实使用了逗号。脑洞大开:)
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
class 并在初始化您的 scanner
实例时执行。然后在调用 Scanner.hasNextBigDecimal()
时使用 groupSeparator
和 decimalSeparator
来检查下一个标记是否与十进制格式匹配。
new BigDecimal(String)
直接使用'.'作为小数点分隔符。
因此,如果您想使用 Scanner.hasNextBigDecimal()
和“.”作为用户输入的小数点分隔符,那么你应该使用 Scanner
s 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);
the program accepts a comma as valid input, but then prints a period as the decimal point.
再次在 Scanner
的 nextBigDecimal()
方法中将所有 groupSeparator
替换为 ""
并将 decimalSeparator
替换为 "."
=49=]。来自 Scanner
class 的一段代码是:
private String processFloatToken(String token) {
String result = token.replaceAll(groupSeparator, "");
if (!decimalSeparator.equals("\."))
result = result.replaceAll(decimalSeparator, ".");
这就是它接受 ,
并打印 .
的原因。