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