我是Matlab的新手,并试图找出当答案实际上在范围内时如何处理溢出和下溢算法。
例如:
x = 2e+160
x = x*x (which returns inf, an overflow)
x = sqrt(x) (which is in the range)
任何帮助表示赞赏。
答案 0 :(得分:7)
我不是Matlab用户,所以请记住这一点。
这背后的主要问题是首先检测上溢/下溢
这有时很难,因为当计算没有返回zero
或inf
时,它们也出现在其他情况下。例如,在数值积分期间,溢出/下溢可能导致结果错误,但仍然是非零数字。
根据我的经验,我认为看看十六进制表示中的数字是有用的(除非您的HW / SW计算在内部使用十进制基数用于变量,这是罕见的,因为大多数HW / SW是二进制)。因此,请以十六进制形式查看数字并检测以下模式:
??????????.????FFFFFFFFFFF?? hex
当您查看小数部分并检测到最低位数附近存在多个FFFFF
时,您的数字最有可能下溢或非常接近该点。每次迭代饱和的时间内,零或者最后的数量通常会减少:
??????????.????FFFFFFFFFFF hex
溢出类似地饱和,但另一方面如下:
FFFFFFFFFFF.FFFFFF?????? hex
对于某些算法来说,在下次迭代之前更精确地对这些数字进行舍入/舍入,但是在应用未知数之前,您需要始终检查一些众所周知的计算示例是否就是这种情况......请看这里:
这是使用这种技术的算法的一个很好的例子
检测上溢/下溢的另一种方法是预测结果数量级。例如
*
将指数汇总在一起/
减去指数sqrt
将指数减半。+
,-
可以导致更大指数的+1/-1
因此,如果您正在处理大/小指数,您就会知道哪些操作可能导致问题泛滥。
最重要的是,当结果精度不适合尾数时,可能会发生下溢。因此,您需要注意增加结果使用位的操作,如:
a*b
a
,b
+,-
最大使用位(a,b) - min使用的位(a,b)/
添加一些位来保存分数...... +,-
操作是最糟糕的,例如,如果添加2^100 + 2^-100
,则结果需要200位尾数,而操作数本身只有1位尾数。
如果检测到上溢/下溢怎么办:
更改等式
如上所述,您可以切换到log
,它可以轻松处理更大范围,但还有其他问题。通常,算法的微小变化也会导致结果按不同因子进行缩放,但子结果仍处于安全范围内,因此您只需要将最终结果缩小到危险范围。在改变方程时,你应该始终考虑结果的精确性和有效性。
使用更大的可变数据类型
如果我没记错,Matlab会有任意精度数字,所以如果需要请使用它们。您还可以使用标准float/double
变量并将值存储到更多变量中,如下所示:
停止迭代
例如,某些算法使用如下系列:
1/1! + 1/2! + 1/3! + ... + 1/n!
在某些情况下,如果您在停止迭代时检测到遇到溢出/下溢的子结果,则仍然具有相对准确的计算结果。不要忘记不要将溢出的子结果包含在最终结果中。