如何处理溢出和下溢?

时间:2015-10-07 22:27:20

标签: matlab math rounding computer-science

我是Matlab的新手,并试图找出当答案实际上在范围内时如何处理溢出和下溢算法。

例如:

x = 2e+160
x = x*x (which returns inf, an overflow)
x = sqrt(x) (which is in the range)

任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:7)

我不是Matlab用户,所以请记住这一点。

这背后的主要问题是首先检测上溢/下溢

这有时很难,因为当计算没有返回zeroinf时,它们也出现在其他情况下。例如,在数值积分期间,溢出/下溢可能导致结果错误,但仍然是非零数字。

根据我的经验,我认为看看十六进制表示中的数字是有用的(除非您的HW / SW计算在内部使用十进制基数用于变量,这是罕见的,因为大多数HW / SW是二进制)。因此,请以十六进制形式查看数字并检测以下模式:

??????????.????FFFFFFFFFFF?? hex

当您查看小数部分并检测到最低位数附近存在多个FFFFF时,您的数字最有可能下溢或非常接近该点。每次迭代饱和的时间内,零或者最后的数量通常会减少:

??????????.????FFFFFFFFFFF hex

溢出类似地饱和,但另一方面如下:

FFFFFFFFFFF.FFFFFF?????? hex

对于某些算法来说,在下次迭代之前更精确地对这些数字进行舍入/舍入,但是在应用未知数之前,您需要始终检查一些众所周知的计算示例是否就是这种情况......请看这里:

这是使用这种技术的算法的一个很好的例子

检测上溢/下溢的另一种方法是预测结果数量级。例如

  • *将指数汇总在一起
  • /减去指数
  • sqrt将指数减半。
  • +-可以导致更大指数的+1/-1

因此,如果您正在处理大/小指数,您就会知道哪些操作可能导致问题泛滥。

最重要的是,当结果精度不适合尾数时,可能会发生下溢。因此,您需要注意增加结果使用位的操作,如:

  • a*b ab
  • 中已用位的总和
  • +,-最大使用位(a,b) - min使用的位(a,b)
  • /添加一些位来保存分数......

+,-操作是最糟糕的,例如,如果添加2^100 + 2^-100,则结果需要200位尾数,而操作数本身只有1位尾数。

如果检测到上溢/下溢怎么办:

  1. 更改等式

    如上所述,您可以切换到log,它可以轻松处理更大范围,但还有其他问题。通常,算法的微小变化也会导致结果按不同因子进行缩放,但子结果仍处于安全范围内,因此您只需要将最终结果缩小到危险范围。在改变方程时,你应该始终考虑结果的精确性和有效性。

  2. 使用更大的可变数据类型

    如果我没记错,Matlab会有任意精度数字,所以如果需要请使用它们。您还可以使用标准float/double变量并将值存储到更多变量中,如下所示:

  3. 停止迭代

    例如,某些算法使用如下系列:

    1/1! + 1/2! + 1/3! + ... + 1/n!
    

    在某些情况下,如果您在停止迭代时检测到遇到溢出/下溢的子结果,则仍然具有相对准确的计算结果。不要忘记不要将溢出的子结果包含在最终结果中。