提问人:starriet 提问时间:3/24/2023 最后编辑:starriet 更新时间:3/25/2023 访问量:472
设置“epsilon”值以避免零除法错误是否有任何最佳实践或注意事项?[关闭]
Are there any best practices or considerations for setting "epsilon" values to avoid zero-division errors? [closed]
问:
我正在考虑在分母上添加一个接近 0 的值,即所谓的“epsilon”,以防止零除法错误,例如:
double EPS = DBL_MIN;
double no_zerodivision_error = 0.0 / (0.0 + EPS);
设置此 epsilon 值时,是否有任何一般的最佳实践或注意事项来防止将来出现问题?
另外,如果我在 和 之间进行选择,两者之间是否有首选值?DBL_MIN
DBL_EPSILON
我以为任何小数字都没问题,但我担心将来可能会遇到一个难以发现的无声问题。
编辑1)在我的应用程序中,有许多正常情况,分母可以为零。这就是为什么我不考虑抛出异常。
编辑2)在某些情况下,这样的“epsilon”被添加到分母中,例如一些深度学习计算。例如,:
# eps: term added to the denominator to improve numerical stability (default: 1e-8)
torch.optim.Adam(..., eps=1e-08, ...)
还有诸如此类的 SO 问题和答案。
答:
#include <limits>
using double_meta=std::numeric_limits<double>;
现在,您可以简单地检查是否需要执行以下技巧:
constexpr double inline zero(double const zr) noexcept {
if constexpr(double_meta::is_iec559)
return zr;
else if (abs(zr)==0.0)
return double_meta::denorm_min();
else
return zr;
};
如果平台支持 iec559,则定义浮点除以零以返回正确签名的版本。否则,是可表示的最小正值,除以导致的值远高于大得多的值(作为最小的正值,其与 1 相加导致值大于 1)。double_meta::infinity()
double_meta::denorm_min()
double
double_meta::epsilon()
顺便说一句,使用并不完全相同。除法可能导致无 NaN 数。因此,代码将依赖于平台,如果浮点除以零是代码的有效部分,这是不可避免的。double::denorm_min()
0.0
更好的办法是守卫师本身;但我无法给出具体的结果常数,因为任何 std 常量的可用性都依赖于 iec559 合规性(在这种情况下,浮点除以零会自动产生无穷大)。
评论
is_iec559
是静态数据成员,而不是函数。还有一个小问题,即使 - 除以零在技术上仍然是未定义的行为,并且在常量表达式中不允许未定义的行为。因此,在 constexpr 上下文中不可能除以零,即使它是真的,例如:godboltdouble_meta::is_iec559()
double_meta::is_iec559
is_iec559 == true
is_iec559
constexper
设置“epsilon”值以避免零除法错误是否有任何最佳实践或注意事项?
不,没有最佳实践。
这通常是一个坏主意,应该避免。在无法避免的情况下,该怎么做取决于应用程序和情况。
评论
x
-EPS
EPS
DBL_MAX