Java中浮点数的精确度探讨

本文探讨了Java中浮点数表示的不精确性,解释了十进制数在二进制下的转换难题,以及为何0.3-0.1不等于0.2。提供了在实际编程中解决浮点数比较问题的方法。

Java中浮点数不精确的讨论
1.十进制中数的表示

我们知道,在十进制中,有些小数是不能被精确便表示的,比如
· 3^(-1)次方,即1/3,这个数是不能使用十进制精确表示的,只能表示为无限循环小数0.333333333333…

2.同一个数在不同进制的表示

同样还以3^(-1)次方为例,其在十进制中不能精确表示,但如果是三进制呢?三进制逢三进一,即整数3在三进制中的表示就是 10(三进制),因此可以得出3^(-1)即1/3在三进制中的表示

· 十进制 3^(-1) --> 三进制 10^(-1),其表示为三进制小数为 0.1(三进制)

也就是说1/3这个数可以在三进制中被精确表示而不能在十进制中被精确表示。

同样的道理,有些在十进制中可以准确表示的数,在二进制中是不一定能够准确表示的。

3.十进制到二进制的小数转换

对于二进制来说,二进制小数点右边能表达的值是 1/2, 1/4, 1/8, 1/16, 1/32, 1/64, 1/128 … 1/(2^n)

我们来试一试如何表达十进制的 0.2 吧。

      0.01(二进制) = 1/4(十进制) = 0.25(十进制) ,太大

      0.001(二进制) =1/8(十进制) = 0.125(十进制) , 太小

      ...同理得下列推算,不再标明进制符号

      0.0011 = 1/8 + 1/16 = 0.1875 , 逼近0.2了

      0.00111 = 1/8 + 1/16 + 1/32 = 0.21875 , 又大了

      0.001101 = 1/8+ 1/16 + 1/64 = 0.203125 还是大

      0.0011001 = 1/8 + 1/16 + 1/128 = 0.1953125 这结果不错

      0.00110011 = 1/8+1/16+1/128+1/256 = 0.19921875 已经很逼近了

其实这就是我们学过逼近法来找到最相近的值,同理计算机是无法准确表示十进制小数0.2的。所以一般要求极其精确的计算时,一般都用java.math.BigDecimal来进行处理,不过对于日常的科学计算,浮点数已经足够了。

4.实例验证
首先我们通过一个判断语句来验证

package cn.theo.java.learn;

public class DoublePrecision {
    public static void main(String[] args) {
        if(0.3-0.1==0.2)
            System.out.println("0.3-0.1==0.2 is right");
        else
            System.out.println("0.3-0.1==0.2 is incorrect");
    }
}

如果计算机中0.3-0.10.2则输出"0.3-0.10.2 is right",若0.3-0.1!=0.2则输出"0.3-0.1==0.2 is incorrect"
输出结果如下:

再一次验证了在计算机中浮点数是不准确的。

让我们看一下计算机中,0.3-0.1的真实结果:
在这里插入图片描述

我们可以看到,真实的结果是0.19999999999999998(这也仅仅是近似值)

因此在精度要求不是特别高的科学计算时,我们一般都引入一个误差值来修正此问题,例如上面判断0.3-0.2==0.1的例子

可进行如下修改:

package cn.theo.java.learn;

public class DoublePrecision {
    public static void main(String[] args) {
        double decimal=0.00000001;
        if(0.3-0.1-0.2<=decimal)
            System.out.println("0.3-0.1==0.2 is right");
        else
            System.out.println("0.3-0.1==0.2 is incorrect");
    }
}

此时可在误差允许内进行逻辑判断。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值