我正在努力理解double的局限性。 0.1不能在有限系统中表示,因为它是重复的二进制值。但是,当我声明一个变量并给它0.1时,它仍然打印为0.1和不 .0999999999999999,1.00000000000000001或类似的东西。但是,如果我添加一个0.1次十次的变量,它就会出现.9999999999999999,这就是我所期望的。
真正的问题是,当我知道这是不可能的时候,为什么它的打印精确到0.1?我有证据证明这不是真正的价值?
double d = 0.1;
System.out.printf("%.16f\n",d);
System.out.printf("%.16f", d + d + d + d + d + d + d + d + d + d);
我要做的是将字符串文字与双重转换进行比较,以查看字符串中的值是否可以用double精确表示。例如:
“。5”== .5?预期答案:是的。
“。1”== .1?预期答案:否。
我正在尝试的比较是
number = new BigDecimal("0.1");
d = number.doubleValue();
if (number.compareTo(new BigDecimal(Double.toString(d))) == 0){
// Doing something
}
任何帮助都可以理解为什么不能区分可以和不能用double表示的值。
答案 0 :(得分:4)
要测试String
是否代表double
值,您可以执行以下操作:
private static boolean isADouble(String s) {
return new BigDecimal(s).equals(new BigDecimal(Double.parseDouble(s)));
}
public static void main(String[] args) {
System.out.println(isADouble("0.1")); // false
System.out.println(isADouble("0.5")); // true
}
这是有效的,因为new BigDecimal(s)
生成的BigDecimal
与String
所代表的值完全相等,而new BigDecimal(Double.parseDouble(s))
是最接近的值{ em> double
到该值。
我将在最后解释为什么number.compareTo(new BigDecimal(Double.toString(d))) == 0
不工作。
当你这样做时
double d = 0.1;
System.out.println(d);
您会得到答案0.1
,因为d
是与“真实”double
最接近的0.1
。 (double d = 0.1;
表示“将d
设为最近double
至0.1
”。撰写时
System.out.println(d + d + d + d + d + d + d + d + d + d);
您看到0.9999999999999999
而不是1
。您没有看到1
的原因是因为double
值比答案更接近于1(实际上一个值本身是double
值)。没有理由为什么答案应该是最接近的double
,因为d
首先不是0.1
(它只是靠近它),而且添加浮点数时会出现不准确的情况。
最后,number.compareTo(new BigDecimal(Double.toString(d))) == 0
不起作用,因为即使number.doubleValue()
不正好0.1
,Double.toString()
仍会将其转换为{{1} }} String
因为没有"0.1"
值更接近“真实”double
。