我如何检查和处理非常接近零的数字
How do I check and handle numbers very close to zero
我有一些数学(在c++中)似乎生成一些非常小的,接近零的数字(我怀疑三角函数调用是我真正的问题),但我想检测这些情况,以便我可以更详细地研究它们。
我目前正在尝试以下,它是正确的吗?
if ( std::abs(x) < DBL_MIN ) {
log_debug("detected small num, %Le, %Le", x, y);
}
其次,数学的本质是三角函数(也就是使用大量的弧度/度转换和sin
/cos
/tan
调用等),我可以做什么样的转换来避免数学错误?
显然对于乘法我可以使用对数变换-还有什么?
与普遍认为的相反,DBL_MIN
不是最小的正double
值,而是最小的正归一化 double
值。通常-对于64位ieee754 doubles
-它是2-1022,而最小的正double
值是2-1074。因此
我目前正在尝试以下,它是正确的吗?
if ( std::abs(x) < DBL_MIN ) {
log_debug("detected small num, %Le, %Le", x, y);
}
可能有肯定的答案。条件检查x
是非规范化(也称为次正常)数还是±0.0。在不了解你具体情况的情况下,我无法判断这个测试是否合适。非规范化的数字可以是合法的计算结果,也可以是舍入的结果,而正确的结果是0。当数学上正确的结果是0时,也有可能四舍五入产生比DBL_MIN
大得多的数字,因此更大的阈值可能是明智的。
如果x
是双精度,那么这种方法的一个问题是,您无法区分x
是合法的零,而x
是小于DBL_MIN
的正值。因此,如果您知道x
永远不会合法地为零,并且您想要查看何时发生下溢,则此操作将有效。
您还可以尝试捕获SIGFPE
信号,该信号将在posix兼容的系统上触发任何数学错误,包括浮点下溢。参见:http://en.wikipedia.org/wiki/SIGFPE
EDIT:需要说明的是,DBL_MIN
不是双精度体可以保存的最大的负值,它是双精度体可以保存的最小的正规范化值。所以你的方法是好的,只要值不能为零。
另一个有用的常量是DBL_EPSILON
,它是可以添加到1.0而不返回1.0的最小双精度值。注意,这是一个比DBL_MIN
大得多的值。但它可能对你们有用因为你们在做趋向于1的三角函数而不是趋向于0的三角函数
由于您使用的是c++,因此最惯用的是使用头文件<limits>
中的std::numeric_limits
。
template <typename T>
bool is_close_to_zero(T x)
{
return std::abs(x) < std::numeric_limits<T>::epsilon();
}
实际使用的容差很大程度上取决于您的问题。请用一个具体的用例来完成你的问题,这样我可以加强我的回答。
还有std::numeric_limits<T>::min()
和std::numeric_limits<T>::denorm_min()
可能是有用的。第一个是T
类型的最小正非规格化值(相当于<cfloat>
的FLT/DBL/LDBL_MIN
),第二个是T
类型的最小正数值(没有<cfloat>
的等效物)。
第一个if
检查实际上只在您的值为零时为真。
对于你的第二个问题,你暗示了很多转换。相反,选择一个单位(度或度)并在该单位中进行所有计算操作。然后在最后,如果需要的话,执行一次到另一个值的转换。
- 查找最接近的大于当前数字的数字的索引
- 必须首先打印向量 v1 中最接近整数 x 的数字<int>
- 如何优化代码以返回最接近给定整数的数字,但给定列表中不存在?
- 查找整数数组中最接近的数字
- 在有条件的向量中找到最接近的数字
- 我需要在给定数字中找到与平均值的最接近(和次要)数字
- 为什么rand()给出相对接近的数字
- 快速获取接近2次幂的数字(浮点)
- 将十进制数字截断为最接近的4个小数和断言
- 从均匀网格中查找最接近的数字
- 如何在 c++ 中获取最接近平均值的数字
- 找到最接近另一个数字 c++ 的数字
- 使用数组查找最接近的数字C++,浮点
- 从一组数字中找出最接近的三个数字值
- 查找数组中与另一个给定数字最接近的数字
- 寻找最接近的数字
- 在两个数组中查找最接近的数字
- 在GTest中,如何检查数字非常接近0?EXPECT_FLOAT_EQ不工作
- 我如何检查和处理非常接近零的数字
- 如果输入的数字不是完全正方形,则找到最接近的完美正方形