为了提高效率,我正在将一些程序从 Matlab 移植到 C++。两个程序的输出完全相同非常重要 (**)。
我面临着此操作的不同结果:
std::sin(0.497418836818383950) = 0.477158760259608410 (C++)
sin(0.497418836818383950) = 0.47715876025960846000 (Matlab)
N[Sin[0.497418836818383950], 20] = 0.477158760259608433 (Mathematica)
因此,据我所知,C++ 和 Matlab 都使用 IEEE754 定义的双精度算术。我想我在某处读到过 IEEE754 允许在最后一位出现不同的结果。使用mathematica来决定,似乎C++更接近结果。如何强制 Matlab 计算 sin 并精确到最后一位,以便结果相同?
在我的程序中,这种行为会导致很大的错误,因为数值微分方程求解器在最后一位不断增加这个错误。但是我不确定 C++ 移植版本是否正确。我猜即使 IEEE754 允许最后一位不同,也能以某种方式保证此误差不会变得更大当在更多 IEEE754 定义的双精度运算中使用结果时(因为否则,根据 IEEE754 标准正确的两个不同程序可能会产生完全不同的输出)。所以另一个问题是我的说法正确吗?
我想得到这两个粗体问题的答案。编辑:第一个问题很有争议,但不太重要,有人可以评论第二个问题吗?
注意:这不是打印错误,以防万一您想检查,这就是我获得这些结果的方法:
https://i.stack.imgur.com/XXH7g.png https://i.stack.imgur.com/XXH7g.png
注意(**):我的意思是,最终的输出,即一些显示一些小数点后 4 位实数的计算结果,需要完全相同。我在问题中谈到的错误变得更大(因为更多的操作,Matlab和C++中的每一个都是不同的),所以最终的差异是巨大的)(如果你很好奇,想看看差异是如何开始变大的,这里是完整的输出[很快就会链接],但这与问题无关)
首先,如果您的数值方法取决于 sin 到最后一位的精度,那么您可能需要使用任意精度库,例如 MPFR。
IEEE754 2008 标准不要求函数正确舍入(但它确实“推荐”)。一些 C libms 确实提供了正确舍入的三角函数:我相信 glibc libm 确实提供了(通常在大多数 Linux 发行版上使用),CRlibm 也是如此。大多数其他现代 libms 将提供 1 ulp 以内的三角函数(即真值两侧的两个浮点值之一),通常称为忠实地圆润,计算速度要快得多。
您打印的这些值实际上都不会以 IEEE 64 位浮点值的形式出现(即使四舍五入):最接近的 3 个值(以全精度打印)是:
0.477158760259608 405451814405751065351068973541259765625
0.477158760259608 46096296563700889237225055694580078125
0.477158760259608 516474116868266719393432140350341796875
您可能需要的可能值是:
- 小数点的精确正弦值 .497418836818383950,即
0.477158760259608 433132061388630377105954125778369485736356219...
(这似乎是 Mathematica 给出的)。
- 最接近 .497418836818383950 的 64 位浮点数的精确 sin:
0.477158760259608 430531153841011107415427334794384396325832953...
在这两种情况下,上面列表中的第一个都是最接近的(尽管仅在 1 的情况下)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)