您没有告诉我们您的递归是什么,但是如果您使用平方根、pow、反正弦或反余弦,则很容易生成具有长操作序列的 NaN。
假设您的计算产生了一个量,称为它x
,它应该是某个角度 θ 的正弦值,并假设基础数学规定它x
必须始终介于 -1 和 1 之间(含)。您通过取 的反正弦来计算 θ x
。
这就是问题所在:在计算机上完成的算术只是对实数算术的近似。IEEE 浮点数的加法和乘法是不可传递的。你很可能得到一个 1.0000000000000002x
而不是 1 的值。取这个值的反正弦,你得到一个 NaN。
一个标准的技巧是防止那些因数值错误而导致的未遂事件。不要使用内置的asin
, acos
,sqrt
和pow
. 使用可以防止诸如asin(1.0000000000000002)
和之类的包装器sqrt(-1e-16)
。将前者设为 pi/2 而不是 NaN,并将后者设为零。诚然,这是一个杂牌,这样做会给你带来麻烦。如果问题是您的计算公式不正确怎么办?将 1.0000000000000002 视为 1 是合法的,但最好不要将值 100 视为 1。asin
包装器的值 100 最好通过抛出异常而不是截断为 1 来处理。
无穷大和 NaN 还有另一个问题:它们会传播。一次计算中的 Inf 或 NaN 很快就会变成数百个值的 Inf 或 NaN,然后是数千个值。我通常让浮点机器在获取 Inf 或 NaN 时引发浮点异常,而不是继续。(请注意:浮点异常不是 C++ 异常。)当你这样做时,你的程序会爆炸,除非你有一个信号处理程序。这不一定是坏事。您可以在调试器中运行该程序并准确找到问题所在。如果没有这些浮点异常,就很难找到问题的根源。