我试图在C语言中创建一个高斯消除器。为此,我需要不时地检查一个矩阵是否在数值上是奇异的:如果某个数(double)非常小。
我的问题是,如果我尝试这样做:

if(0 == matrix->items[from]){
        fprintf(stderr,"Matrix is still singular after attempting pivot. Exitig.\n");
}

这决不会是真的。由于double的不精确性,它永远不会精确到0。然而,当试图运行程序时,类似这样的情况会用inf或NaN填充数字,这取决于是用它及其组合进行乘法还是除法。
为了过滤这些,我需要这样的东西:
#define EPSILON very_small
// rest of the code
if(matrix->items[from] < EPSILON){
     ...singular
}

这个EPSILON的推荐值是多少?是双精度的绝对精度,还是更大一点的数值?
顺便说一句,如果把它定义为上面提到的宏,或者像这样使用它,那会更好:
const double EPSILON = ...;

对不起,如果我说得不够清楚,英语不是我的母语。
谢谢你的回复。

最佳答案

我需要检查矩阵在数值上是否是奇异的
通常这是通过防止double溢出来检测的。

// Check if 1.0/determinant will overflow.
if (fabs(determinant) <= 1.0/(0.99*DBL_MAX)) {
  Handle_Singular_Case()
} else {
  one_over_det = 1.0/determinant;
}

使用DBL_EPSILON(例如:2e-16)通常是错误的解决方案。double数学需要相对比较,以确保良好的计算远离1.0量级。
// Rarely the right thing to do.
#define EPSILON DBL_EPSILON
if(fabs(matrix->items[from]) < EPSILON){

然而,这是非常上下文敏感的@Weather Vane
然而,OP的真正问题当然在这里:“当试图运行这个程序时,像这样的情况用inf或NaN填充数字,这取决于是用它及其组合进行乘法还是除法。”。可以使用各种技术来避免这个问题,例如使用partial pivoting进行消除。
为了解决这个问题,最好张贴代码和样本数据。

关于c - 推荐的最小两倍的最小ε是多少?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42913943/

10-10 13:29