我试图在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/