如果double类型可以处理数字4.35和435,为什么4.35*100的计算结果为434.99999999999994?

Lyd*_*Lyd 2 java printing string math floating-point

据我所知,有些数字不能用二进制精确表示,这就是为什么浮点运算有时会给我们带来意想不到的结果; 像4.35*100 = 434.99999999999994.与十进制中的1/3相似的东西.

这是有道理的,但这引发了另一个问题.似乎在二进制中4.35和435都可以精确表示.那就是它停止对我有意义的时候.为什么4.35*100的评估结果为434.99999999999994?435和4.35在双重类型动态中具有精确表示:

double number1 = 4.35;
double number2 = 435;
double number3 = 100;
System.out.println(number1); // 4.35
System.out.println(number2); // 435.0
System.out.println(number3); // 100.0
// So far so good. Everything ok. 

System.out.println(number1 * number3); // 434.99999999999994 !!!
// But 4.35 * 100 evaluates to 434.99999999999994
Run Code Online (Sandbox Code Playgroud)

为什么?

编辑:此问题被标记为重复,但事实并非如此.正如您在接受的答案中所看到的,我的困惑在于实际值与印刷值之间的差异.

Roh*_*ain 12

似乎在二进制中4.35和435都可以精确表示.

我看到你了解浮点数是如何在内部表示的.至于你的疑问,没有4.35没有确切的二进制表示.所以问题是,为什么打印第一个打印语句4.35.

发生这种情况是因为System.out.println()调用了Double.toString(double)方法,而方法又使用FloatingDecimal#toJavaFormatString()方法,该方法在传递的double参数内部执行一些舍入.您可以浏览我链接的源代码.

要查看实际值4.35,请尝试使用:

BigDecimal bd = new BigDecimal(number1);
System.out.println(bd);
Run Code Online (Sandbox Code Playgroud)

这将打印:

4.3499999999999996447286321199499070644378662109375
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您可以创建一个BigDecimal将double值传递为参数的对象,而不是打印double值.BigDecimal表示任意精度带符号十进制数.所以它给你的确切值4.35.


rge*_*man 8

你是对的,有时浮点运算会产生意想不到的结果.

您4.35可以在浮点中精确表示的断言是不正确的,因为它不能表示为终止二进制十进制. 100显然可以准确地表示,因此对于结果434.99999999999994,`4.35不能准确表示.

要准确地用浮点表示,数字必须能够转换为分母,其中分母只有2的幂(并且它必须不能精确到超过浮点类型的最大精度你'正在使用).在这种情况下,4.35是4 7/20,并且分母具有因子5,因此该数字不能精确地以二进制表示.

  • 当Java将诸如"4.3499999999999996447286321199499070644378662109375"之类的数字转换为"String"时,它会将其四舍五入为"4.35",但该舍入点会显示"434.99999999999994"的不精确表示,因为它看起来像是舍入点超过了最后一位数对于后者而不是前者. (3认同)