我正在尝试对用C ++和Matlab编写的算法进行等效性测试。 该算法包含某种循环,运行时间超过1000次。它有算术运算和一些数学函数。
我手动将初始输入馈送到两个平台(如a = 1.767,b = 6.65,...),当我检查这些输入的十六进制表示时,它们是相同的。所以输入没问题。并通过一个带有16位十进制数字的文本文件将c ++的输出输出到matlab。 (我使用“setprecision(32)”声明)
但问题来了;虽然在两个代码的第614步之后,所有结果都完全相同,在615的步骤中我得到了关于2.xxx..xxe-19的差异?在此步骤之后,错误变得越来越大,并且在运行结束时它大约是5.xx..xxe-14。
0x3ff1 3e42 a211 6cca ---> [C ++功能] ---> 0x3ff4 7619 7005 5a42
0x3ff1 3e42 a211 6cca ---> [MATLAB功能] ---> ans
ans - 0x3ff4 7619 7005 5a42
= 2.xxx..xxe-19
我搜索了matlab如何表现数字并发现了非常有趣的东西,比如“非规范化的尾数”。虽然realmin是关于e-308的,但通过对尾数进行非规范化,matlab具有关于e-324的最小实数。另外,matlab比“c ++”拥有更多的“pi”或“exp(1)”数字。
另一方面,matlab帮助说无论它显示什么格式,matlab都会在内部使用双精度。
所以,如果有人解释这些差异的确切原因,我真的很感激?我们如何在matlab和c ++上进行等价测试?
答案 0 :(得分:10)
x86 CPU中有一点关于浮点数。在内部,浮点单元使用10字节的寄存器,即80位。此外,CPU具有一个设置,用于指示是否应使用32位(float
),64位(double
)或80位精度进行浮点计算。精度较低意味着执行浮点运算速度更快。 (32位模式过去常用于视频游戏,速度接管精度)。
由此我记得我跟踪了一个计算库(dll)中的一个错误,它给出了相同的输入并没有给出相同的结果,无论它是从测试C ++可执行文件还是从MatLab启动的。此外,这没有发生在调试模式下,仅在Release!中
最后的结论是MatLab确实将CPU浮点精度设置为80位,而我们的测试可执行文件没有(并保留默认的64位精度)。此外,这种计算不匹配没有发生在调试模式,因为所有变量都被写入内存为64位double
变量,然后从那里重新加载,使额外的16位无效。在释放模式下,一些变量被优化(不写入存储器),并且所有计算仅使用浮点寄存器,在80位上完成,保持额外的16位非零值。
不知道这是否有帮助,但也许值得了解。
答案 1 :(得分:4)
之前发生了similar discussion,结论是IEEE 754容忍了超越函数(cos,sin,exp等)的最后一位的错误。因此,您不能指望MATLAB和C之间的结果完全相同(甚至不同编译器中编译的C代码相同)。
答案 2 :(得分:0)
我可能在这里偏离轨道并且您可能已经研究过这种可能性,但C ++和Matlab之间可能存在数学库函数(sin()cos()和exp()的差异)你提到的)是在内部实施的。最终,必须使用某种函数逼近来生成函数值,如果这些方法之间存在某些差异,那么可能这可能会在大量迭代中以数值舍入误差的形式表现出来。
这个问题基本上涵盖了我的建议How does C compute sin() and other math functions?