[原创]MATLAB中关于0.1-0.3+0.2不等于0的解释
(2012-10-12 18:47:43)
标签:
matlab技术论坛杂谈 |
分类: MATLAB |
[原创]MATLAB中关于0.1-0.3+0.2不等于0的解释
现在MATLAB的Command
Window中进行一组运算
为什么上式的结果不为0呢??且不同的运算顺序结果不一样呢??下面我们就详细解释这个原因!
在本教程之前推荐您先了解下《1985年IEEE发布了二进制浮点运算标准754-1985》。根据IEEE浮点数运算标准,我编写了两个简单的程序,用于ieee数值和double数值之间的转换。 利用上面的double2ieee函数尝试得到0.1的IEEE编码 也就是说0.1的IEEE编码就是上面那一坨0和1(晕吧),其实这串二进制代表的真实数据略大于0.1,也就是说 傻子都知道计算机是二进制存储数据的,由于0.1没有精确的IEEE编码,根据就近一致原则,0.1采用的IEEE编码就采用最近的第二个编码。
现在讨论下上面两个编码到底代表什么数据呢?好,使用ieee2double()函数来测试下 也就是说那一大串0和1对应于上面那两个分数(为了保留足够的精度,这里使用分数显示出来,如果直接采用小数显示,您不会看到区别的)!
同理可以得到0.2和0.3的IEEE编码,以及相应的IEEE编码代表的真实数值! 现在模拟计算0.1+0.3-0.2的结果 也就是说在IEEE标准下,0.1+0.3-0.2的结果为1/36028797018963968≈2.7756e-17,显然这个不等于零!!
接下来讨论下,为什么0.1-0.3+0.2和0.1+0.2-0.3的结果不一样?
这个主要是由于加法运算是左结合的,也就是说0.1-0.3+0.2是先计算0.1-0.3,得到-0.2;而0.1+0.2-0.3是先计算0.1+0.2,得到0.3。-0.2和0.3的IEEE编码当然是不同的,相应的误差也有区别,于是得到最后结果也就不同了。至于具体多少,大家可以使用本文提供的两个函数进行测试和推到下!
在本教程之前推荐您先了解下《1985年IEEE发布了二进制浮点运算标准754-1985》。根据IEEE浮点数运算标准,我编写了两个简单的程序,用于ieee数值和double数值之间的转换。 利用上面的double2ieee函数尝试得到0.1的IEEE编码 也就是说0.1的IEEE编码就是上面那一坨0和1(晕吧),其实这串二进制代表的真实数据略大于0.1,也就是说 傻子都知道计算机是二进制存储数据的,由于0.1没有精确的IEEE编码,根据就近一致原则,0.1采用的IEEE编码就采用最近的第二个编码。
现在讨论下上面两个编码到底代表什么数据呢?好,使用ieee2double()函数来测试下 也就是说那一大串0和1对应于上面那两个分数(为了保留足够的精度,这里使用分数显示出来,如果直接采用小数显示,您不会看到区别的)!
同理可以得到0.2和0.3的IEEE编码,以及相应的IEEE编码代表的真实数值! 现在模拟计算0.1+0.3-0.2的结果 也就是说在IEEE标准下,0.1+0.3-0.2的结果为1/36028797018963968≈2.7756e-17,显然这个不等于零!!
接下来讨论下,为什么0.1-0.3+0.2和0.1+0.2-0.3的结果不一样?
这个主要是由于加法运算是左结合的,也就是说0.1-0.3+0.2是先计算0.1-0.3,得到-0.2;而0.1+0.2-0.3是先计算0.1+0.2,得到0.3。-0.2和0.3的IEEE编码当然是不同的,相应的误差也有区别,于是得到最后结果也就不同了。至于具体多少,大家可以使用本文提供的两个函数进行测试和推到下!