我向初学程序员讲授Java,我的许多荷兰学生在他们第一次使用Scanner输入浮点值时感到困惑。
nextDouble()的默认行为是查阅计算机的区域设置。当设置为荷兰语时,这意味着必须使用小数逗号。
另一方面,System.out.println似乎不考虑语言环境并使用小数点。
例如考虑以下输出(用户输入为粗体):
给出低于10.0的数字
10,5
抱歉,10.5不低于10.0
(如果输入10.5,将抛出InputMismatchException。)上面的输出由以下片段生成
Scanner scanner = new Scanner( System.in );
double limit = 10.0;
System.out.println( "Give a number below "+limit );
double x = scanner.nextDouble();
if (x >= limit ) {
System.out.println( "Sorry, "+x+" is not below "+limit );
}
这是库中的不一致还是以错误的方式使用它?
答案 0 :(得分:2)
提供给此调用的参数
System.out.println( "Sorry, "+x+" is not below "+limit );
是一个String
,它是连接一些String
文字和一些double
值的结果。
如果只有一个操作数表达式是String类型,则在另一个操作数上执行string conversion (§5.1.11)以生成 运行时的字符串。
然后
原始类型
x
的值T
首先转换为参考值 好像通过将它作为参数提供给适当的类实例 创作表达式(§15.9):
- 如果
T
为double
,请使用new Double(x)
。
然后继续说
否则,转换就像通过调用一样执行 没有参数的引用对象的
toString
方法;但如果 调用toString
方法的结果是null
,然后是字符串"null"
而是用来代替。
Double#toString
的javadoc解释了格式
返回此
Double
对象的字符串表示形式。原始人 此对象表示的double
值将转换为字符串 就像一个参数的方法toString
一样。
这是重载的toString(double)
方法
返回double参数的字符串表示形式。所有人物 下面提到的是ASCII字符。
- 如果参数为
NaN
,则结果为字符串"NaN"
。- 否则,结果是一个字符串,表示参数的符号和大小(绝对值)。如果标志是否定的, 结果的第一个字符是
'-' ('\u002D')
;如果标志是 正面,结果中不显示任何符号字符。至于 幅度m:
- 如果
m
为无穷大,则由字符"Infinity"
表示;因此,正无穷大产生结果"Infinity"
和 负无穷大产生结果"-Infinity"
。- 如果
m
为零,则由字符"0.0"
表示;因此,负零产生结果"-0.0"
并产生正零 结果“0.0”。- 如果
m
大于或等于10^-3
但小于10^7
,则表示为m的整数部分,十进制形式,不含 前导零,后跟'.' ('\u002E')
,后跟一个或多个 表示m
的小数部分的十进制数字。- 如果m小于
10^-3
或大于或等于10^7
,则表示为所谓的“计算机化科学记数法”。让 n是唯一的整数,10^n ≤ m < 10n+1
;然后让一个人成为 数学上精确的m和10^n
的商,以便1 ≤ a < 10
。该 然后将幅度表示为a
的整数部分,作为单个 十进制数字,后跟'.' ('\u002E')
,后跟十进制数字 代表a
的小数部分,后跟字母'E'
('\u0045')
,后跟n表示十进制整数,如 由方法Integer.toString(int)
生成。
m
或a
的小数部分必须打印多少位数? 必须至少有一个数字来表示小数部分,并且 超出那个数量,但只需要更多,更多的数字 唯一地将参数值与相邻的类型值区分开来 双。也就是说,假设x
是精确的数学值 由此方法生成的十进制表示法表示 有限的非零参数d
。然后d
必须是最近的double
值 到x
;或者,如果两个double
值同等接近x
,那么d
必须为d
其中之一,0
必须具有最重要的意义 是NumberFormat
。要创建浮点值的本地化字符串表示, 使用
double
的子类。
介绍了如何正确格式化printf
。
或者,使用($) :: (a -> b) -> a -> b
并为浮点值提供适当的格式模式。
答案 1 :(得分:1)
String concatenation,String.format,printf,Double.toString,Double.valueOf都使用十进制 point 而没有千分隔符,与java源代码兼容。幸运的是,这是基本的非本地化表示,对于数据的文本传输非常有用 。
Scanner,NumberFormat,MessageFormat涉及本地化,有时有点尴尬。它们用于高级代码,用于用户交互。还有千分隔符。
一个人必须选择一个。使用最低限度的本地化数字是一项很好的练习。或者在懒惰时,可以使用Double.parseDouble
代替Scanner
或:
Scanner scanner = new Scanner(System.in).useLocale(Locale.US);
另一个格式/值问题是double的使用,它是一个近似值,并且没有精度,作为固定点BigDecimal。双精度应该用于快速计算,BigDecimal用于财务精确度。
new BigDecimal("0.20") // Precision of 2, no loss.
0.20 // Not exactly 0.20, no precision on printing