Fortran Coder

标题: 简单的减法,release和debug的计算结果为什么不一样? [打印本页]

作者: 大树    时间: 2019-5-21 20:58
标题: 简单的减法,release和debug的计算结果为什么不一样?
采用Fortran双精度计算c=c1^2 - (c3^2)*c2,分别用debugrelease模式编译出可执行程序,编译器是intel Parallel Studio XE 2018。运行后发现计算结果在小数点最后一位(第15位)上不一样。
于是输出c1,c2和c3检查差异的来源。虽然双精度的有效位数是小数点后15位,但是强制输出小数点后18位。结果显示c1,c2和c3在两种模式中直到小数点后18位都完全相同,但是(c3^2)*c2的结果却出现差异。

数据如下,黑色加粗部分表示15位小数点。
c1=3.745496116952728386E-04,  c2=2.364288313097455060E-03,  c3=7.071067835889063291E-01,

c1^2在两种模式下结果完全一样,等于    3.745496116952728386E-04
(c3^2)*c2在两种模式中分别等于debug: 1.182144164581275247E-03,   release: 1.182144164581275031E-03,
相减得到c在两种模式中分别等于debug: -8.075945528860024088E-04, release: -8.075945528860021920E-04。

(c3^2)*c2的差异出现在16位及以后,但是影响到了c的第十五位。说明16位以后的数字也参与了计算,并对结果产生了影响。
那么问题来了,
1. 双精度只能保存到小数点后15位,16到18位的小数点是怎么来的,为什么能参与计算?
2.两种模式中c1, c2和c3直到小数点18位完全一样,为什么通过乘法运算得到的(c3^2)*c2在小数点后第16位上出现差异?


作者: fcode    时间: 2019-5-22 08:58
这都很正常呀。
因为计算机是二进制。

第一个问题:
如果你不太能理解二进制和十进制的实数转换。那么你可以想象一下三进制和十进制的转换。

1/3 对三进制( 0.1(3) )来说,是整的1位小数。但是对十进制来说,就是无限(循环)小数。

所以,计算机里采用二进制,双精度取了52位小数,所以是    log10(2^52)= 15.653 位有效数字。
计算机内部是只取了52位二进制小数的,只是转换成十进制显示的时候,多余的数字出现了。

第二个问题:
不同的优化算法下,相同的计算由于第53位或者更低的位数下的影响。浮点数计算会有舍入误差。
这也是很正常的事情。
这个问题的细节,你恐怕要去看CPU方面的手册了。
作者: 大树    时间: 2019-5-22 11:24
fcode 发表于 2019-5-22 08:58
这都很正常呀。
因为计算机是二进制。

多谢回复,第一个问题我大概理解了
作者: pasuka    时间: 2019-5-25 11:21
本帖最后由 pasuka 于 2019-5-25 11:25 编辑

lz需要了解IEEE-754和IEEE-754 (2008)规范对于计算机浮点数的约定
传送门:
https://docs.oracle.com/cd/E7194 ... 9878.html#scrolltoc
浅尝即止的话,把表10 存储格式的范围和精度 记住就能在BATH码农面试中脱颖而出了


作者: 大树    时间: 2019-6-4 20:23
pasuka 发表于 2019-5-25 11:21
lz需要了解IEEE-754和IEEE-754 (2008)规范对于计算机浮点数的约定
传送门:
https://docs.oracle.com/cd/E7 ...

厉害,有空学习一下




欢迎光临 Fortran Coder (http://bbs.fcode.cn/) Powered by Discuz! X3.2