减去两个十进制数字,给出奇怪的输出

pra*_*nth -3 java floating-point

虽然我很开心Java Puzzlers的代码(我没有这本书),但我遇到了这段代码

public static void main(String args[]) {
        System.out.println(2.00 - 1.10);
    }
Run Code Online (Sandbox Code Playgroud)

输出是

0.8999999999999999
Run Code Online (Sandbox Code Playgroud)

当我尝试将代码更改为

2.00d - 1.10d 我仍然得到相同的输出 0.8999999999999999

对于,2.00d - 1.10f输出为0.8999999761581421
For,2.00f - 1.10d输出为0.8999999999999999
For,2.00f - 1.10fOutput为0.9

为什么我不能像0.9第一个那样获得输出?我不能用这个做任何头或尾?有人可以清楚说明这一点吗?

Rah*_*thi 6

因为在Java中,双值是IEEE浮点数.

解决方法可能是使用Big Decimal类

不可变的,任意精度的带符号十进制数.BigDecimal由任意精度整数非标度值和32位整数标度组成.如果为零或正数,则比例是小数点右侧的位数.如果是负数,则将数字的未缩放值乘以10来表示比例的否定.因此,BigDecimal表示的数字的值是(unscaledValue×10 ^ -scale).

另外,您可能还想查看 关于IEEE 754的维基百科文章如何在大多数系统上存储浮点数.

您对浮点数执行的操作越多,可能会出现更严重的舍入错误.


Ric*_*gle 5

在二进制0.1中是0.00011001100110011001100110011001 .....,

因此,它不能完全用二进制表示.根据你圆润的地方(浮动或双重),你得到不同的答案.

所以0.1f = 0.000110011001100110011001100和0.1d = 0.0001100110011001100110011001100110011001100110011001

您注意到该数字在1100周期内重复.但是浮动和双精度将它分成循环中的不同点.因此,一个错误四舍五入,另一个错误; 导致差异.

但最重要的是; 永远不要假设浮点数是准确的

  • "永远不要相信浮点数是准确的"是不好的建议.正确的建议是理解浮点运算并在适当的谨慎和设计下使用它.浮点运算由IEEE 754标准明确规定,并且在完成适当的知识和关注时可用于精确计算. (2认同)