【问题标题】:How to deal with overflow and underflow?如何处理上溢和下溢?
【发布时间】:2016-01-05 08:21:45
【问题描述】:

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

例如:

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

感谢任何帮助。

【问题讨论】:

  • 没有一个通用的答案。这取决于您要做什么,是否可以取消溢出。另外,检查vpa
  • 根据应用程序,您可能希望使用数字的对数。更改您的算法以处理日志。

标签: matlab math rounding computer-science


【解决方案1】:

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

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

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

根据我的经验,我倾向于认为以十六进制表示形式查看数字很有用(除非您的硬件/软件计算在内部使用十进制基数作为变量,因为大多数硬件/软件都是二进制的,所以这种情况很少见)。所以查看十六进制形式的数字并检测如下模式:

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

当您查看小数部分并检测到许多FFFFF 存在于最低数字附近时,那么您的数字最有可能下溢或非常接近该点。零的数量或最后的数量通常随着每次迭代饱和而减少:

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

溢出类似地饱和,但在另一边是这样的:

FFFFFFFFFFF.FFFFFF?????? hex

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

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

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

  • * 将指数相加
  • / 减去指数
  • sqrt 将指数减半
  • +,- 可以导致更大指数的+1/-1

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

此外,当您的结果精度不适合尾数时,可能会发生下溢。因此,您需要小心增加结果的使用位的操作,例如:

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

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

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

  1. 改变方程式

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

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

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

  3. 停止迭代

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

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

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

【讨论】:

  • 非常好的答案(并且因为缺少大量项目符号而+1:)。只是一个 matlab 注释:matlab 默认使用双精度数,但是有一个符号数学工具箱,它允许使用他的评论中提到的命令vpa(@LuisMendo)进行可变精度算术。这将允许精确地表示x=vpa('2e160'),但请注意,这不等于x=vpa(2e160),后者已经被表示为双精度(失去精度)。
  • 干得好!显然我刚刚回答了duplicate,您可以在其中找到此代码的 MATLAB 代码。
猜你喜欢
  • 2011-08-12
  • 2019-05-17
  • 2013-07-10
  • 1970-01-01
  • 2020-02-19
  • 2011-01-24
  • 1970-01-01
相关资源
最近更新 更多