我是 Matlab 新手,试图弄清楚当答案实际上在范围内时如何处理溢出和下溢算术。
例如:
x = 2e+160
x = x*x (which returns inf, an overflow)
x = sqrt(x) (which is in the range)
任何帮助表示赞赏。
我不是 Matlab 用户,所以请记住这一点。
这背后的主要问题是首先检测上溢/下溢
这有时很困难,因为它们也会出现在计算不返回的其他情况下zero
or inf
。例如,在数值积分期间,上溢/下溢可能会导致结果错误,但仍然是非零数。
根据我的经验,我倾向于认为查看十六进制表示形式的数字很有用(除非您的硬件/软件计算在内部使用十进制基数来表示变量,这种情况很少见,因为大多数硬件/软件都是二进制的)。因此,查看十六进制形式的数字并检测如下模式:
??????????.????FFFFFFFFFFF?? hex
当你查看小数部分并发现这么多FFFFF
出现在最低数字附近,那么您的数字是最有可能的下溢或非常接近该点。零的数量或最后的数量通常会随着每次迭代的饱和而减少:
??????????.????FFFFFFFFFFF hex
溢出同样饱和,但在另一侧是这样的:
FFFFFFFFFFF.FFFFFF?????? hex
对于某些算法来说,在下一次迭代之前对这些数字进行向上/向下舍入更为精确,但在应用于未知数之前,您始终需要检查一些众所周知的计算示例是否属于这种情况......请看这里:
这是使用这种技术的算法的一个很好的例子
检测上溢/下溢的另一种方法是预测结果数大小。例如
-
*
将指数相加
-
/
减去指数
-
sqrt
将指数减半
-
+
,-
可以导致+1/-1
较大指数的
因此,如果您正在处理大/小指数,您知道哪些操作可能会导致溢出问题。
最重要的是,当结果精度不适合尾数时,可能会发生下溢。因此,您需要小心增加结果已使用位的操作,例如:
-
a*b
中已用位的总和a
,b
-
+,-
(a,b) 的最大使用位 - (a,b) 的最小使用位
-
/
添加一些位来保存分数...
The +,-
操作是最糟糕的,例如如果您添加2^100 + 2^-100
那么结果需要 200 位尾数,而操作数本身只有 1 位尾数。
如果检测到上溢/下溢该怎么办:
-
变化方程
如前所述,您可以切换到log
它可以轻松处理更大的范围,但也存在其他问题。通常情况下,算法的轻微变化可能会导致结果按不同的因子缩放,但子结果仍在安全范围内,因此您只需要最终结果即可缩放到危险范围。在更改方程时,您应该始终考虑结果的精度和有效性。
-
使用更大的变量数据类型
如果我没记错的话,Matlab 有任意精度的数字,所以如果需要的话可以使用它们。您也可以使用标准float/double
变量并将值存储到更多变量中,如下所示:
-
停止迭代
例如,某些算法使用以下系列:
1/1! + 1/2! + 1/3! + ... + 1/n!
在某些情况下,如果您在停止迭代时检测到子结果溢出/下溢,您仍然可以获得相对准确的计算结果。不要忘记不要将溢出的子结果包含到最终结果中。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)