返回

常识也能踩坑?我遇到了一个让人抓狂的常识坑!

后端

大家好,我是歪歪。踩坑了啊,又踩坑了啊!这次踩到一个特别无语的常识坑。知道真相的那一刻,人就是整个麻掉。

先上个代码:

public static void main(String[] args) {
    double a = 0.1;
    double b = 0.2;
    if (a + b == 0.3) {
        System.out.println("a + b 等于 0.3");
    } else {
        System.out.println("a + b 不等于 0.3");
    }
}

你先别问为什么计算不用 BigDecimal,反正程序里面就是有一个类似于这个的代码,然后这个代码跑出来,控制台打印的是:

a + b 不等于 0.3

当时我整个人就裂开了。0.1 加 0.2 不等于 0.3,这他妈还用说吗?不是,我当然知道 0.1 加 0.2 不等于 0.3,问题是为什么这个代码会打印出 "a + b 不等于 0.3"?

于是我开始各种查资料,各种问人,最后终于搞清楚了。原来,这是浮点型精度的问题。

浮点型是计算机用来表示实数的一种数据类型。浮点型的数据是用一个尾数和一个指数来表示的。尾数是实数的小数部分,指数是实数的整数部分。

在计算机中,浮点型数据是使用二进制来存储的。二进制只有 0 和 1 两种数字,所以浮点型数据只能表示有限个实数。

当计算机将一个十进制实数转换成浮点型数据时,它会对实数进行四舍五入,以使其能够用二进制来表示。

这就是为什么 0.1 加 0.2 不等于 0.3 的原因。因为 0.1 和 0.2 在转换成浮点型数据时都被四舍五入了,导致它们在计算机中存储的值并不是真正的 0.1 和 0.2。

浮点型精度的问题在编程中经常会遇到。比如,在计算货币时,如果使用浮点型数据类型,就可能会出现精度问题,导致计算结果不准确。

为了避免浮点型精度的问题,我们可以使用 BigDecimal 数据类型。BigDecimal 数据类型是一个任意精度的非负十进制数。BigDecimal 数据类型在进行计算时不会进行四舍五入,因此可以保证计算结果的准确性。

当然,使用 BigDecimal 数据类型也有缺点。BigDecimal 数据类型占用更多的内存,并且计算速度也比浮点型数据类型慢。因此,在选择数据类型时,需要权衡利弊。

以上就是我踩到的一个常识坑。希望大家能够引以为戒,在编程中避免踩到类似的坑。

最后,再给大家总结一下浮点型精度问题的几点注意事项:

  1. 浮点型数据在计算机中是使用二进制来存储的。
  2. 当计算机将一个十进制实数转换成浮点型数据时,它会对实数进行四舍五入,以使其能够用二进制来表示。
  3. 浮点型精度的问题在编程中经常会遇到。
  4. 为了避免浮点型精度的问题,我们可以使用 BigDecimal 数据类型。
  5. BigDecimal 数据类型是一个任意精度的非负十进制数。
  6. BigDecimal 数据类型在进行计算时不会进行四舍五入,因此可以保证计算结果的准确性。
  7. 使用 BigDecimal 数据类型也有缺点。BigDecimal 数据类型占用更多的内存,并且计算速度也比浮点型数据类型慢。
  8. 在选择数据类型时,需要权衡利弊。