对 double 不能算出精确值问题的思考

我知道 double型数据在内存的表示遵循IEEE标准,对于0.1  ,1.1,2.1等等 很多数,不能被精确的表示为double数据

只能被表示为最接近它的double值

先来看一段程序

double d1 = 0.9;
double d2 = 0.1;
double d3 = 1.1;
System.out.println(d1);
System.out.println(d2);
System.out.println(d3);

输出为:

0.9
0.1
1.1


输出结果  并没有 变成我们想象的那种 0.99999999999999 或者1.10000000000000001

这说明0.1, 1.1 本身就是double型最接近它们的值。

再来看一段:

System.out.println(5.0 - 4.1);
System.out.println(5.0 - 3.1);
System.out.println(5.0 - 2.1);
System.out.println(5.0 - 1.1);
System.out.println(5.0 - 0.1);
System.out.println("******************");
System.out.println(4.0 - 3.1);
System.out.println(3.0 - 2.1);
System.out.println(2.0 - 1.1);
System.out.println(1.0 - 0.1);
System.out.println("******************");
System.out.println(4.0 - 0.1);
System.out.println(3.0 - 0.1);
System.out.println(2.0 - 0.1);
System.out.println(1.0 - 0.1);


输出结果:

0.9000000000000004
1.9
2.9
3.9
4.9
******************
0.8999999999999999
0.8999999999999999
0.8999999999999999
0.9
******************
3.9
2.9
1.9
0.9

这些结果开始时超出了我的想象

从第一组数据看,相差大于1的,好像结果是对的,

从第二组看,相差小于1的,结果居然也有对的,

从第三组看,和0.1作差的全是对的。


那么  0.1跟1.1,2.1等等其它数有什么不同呢? 相差大于1的时候结果怎么就变对了呢?

问题就出现在0.1 的IEEE表示上,

因为它标准化的时候0.1要小数点被向右移位,而其它数 小数点像左移

这样0.1算的实际位数要比 2.1,3.1等等 其它数多几位, 即0.1本身的double型表示比2.1中的那个0.1要精确


在做double型减法运算时,需要经过对阶,求和,右规,舍入(0舍1入)操作

如5.0-0.1 对阶需要移动5位,计算舍入后最后得出4.9。这个4.9中的0.9其实是一个不精确的数,但0.9比0.8999999999999或者0.90000000001更接近真实值。

而5.0-4.1对阶时 不需要移动,计算舍入后最后得出0.9000000000000004, 这个数也不是一个精确值,只是因为真实值相对于0.9000000000000003或者0.9000000000000005,跟接近与0.9000000000000004.


假如我的想法正确,那么就是对阶移动位数比较多时,计算机能得出跟数学计算一样的值,否则得出一个其他值

验证

System.out.println(100.0 - 0.1);
System.out.println(100.0 - 99.1);

99.9
0.9000000000000057

综上,结论是对的。

 

同样的道理,假如 某个数a 大于2^54;  因为double型的尾数是52位, 加上标准化的一位 共53位,

那么将a转换为double型时,采用恒掉的方法,只能取前53位, 又假如 a的第54位为0,  则(double)a+1 = = (double)a 





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值