2017-03-20 15 views
0

가우스 제거기를 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에 대한 권장 값 무엇입니까 :이를 필터링하기 위해

, 나는 이런 식으로 뭔가를해야 할 것인가? 그것은 절대 정확도가 double인지, 아니면 좀 더 큰 값입니까? 위와 같이 매크로로 정의하거나 좋아하여, 더 나은 될 것입니다 방법으로

는 : 나는 충분히 명확되고 있지 않다 경우

const double EPSILON = ...; 

죄송합니다, 영어는 내 모국어가 아닌.

답장을 보내 주셔서 감사합니다.

+3

는'기록하지 마십시오. 그리고 현대 컴파일러는 우연히 비교 대신 할당을 사용하면 불평 할 것이므로 더 이상 "좋은 *"방법은 아닙니다. –

+0

올바른 값은 'DBL_EPSILON'뿐입니다. – Olaf

+2

@Olaf 왜 유일한 올바른 값이다? – immibis

답변

2

는 I 매트릭스 수치

보통이 double 오버 플로우를 방지하여 검출 단수인지를 확인할 필요가있다. DBL_EPSILON (예 : 2E-16)를 사용

// 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; 
} 

보통 잘못 솔루션이다. double 수학은 상대적 인 비교를 통해 1.0 크기보다 멀리 좋은 계산을 보장합니다.

// Rarely the right thing to do. 
#define EPSILON DBL_EPSILON 
if(fabs(matrix->items[from]) < EPSILON){ 

그러나 이는 매우 상황에 민감합니다. @Weather Vane입니다.


는 그러나 영업 이익의 진짜 문제는 여기에 확실히 : "프로그램을 실행하려고 할 때,이 같은 경우는, INF 또는 NaN이 함께 숫자를 채우기에 따라 곱 또는 그 조합으로 분할 여부.". 다양한 기술을 사용하여 partial pivoting으로 제거하는 것과 같이이 문제를 피할 수 있습니다.

문제를 해결하기 위해 최선의 코드 및 샘플 데이터를 게시합니다. `([에서] 0 ==이 매트릭스 -> 항목), 정말 추한 경우

+1

일반적으로 수치 안정성을위한 알고리즘을 구조화하고 특히이 목적을 위해 부분 피벗 팅에 대한 좋은 관찰. 훌륭한 프로그램으로 수학을 변환하는 것은 수식을 선택한 언어의 구문으로 변환하는 것만 큼 간단하지 않습니다. –

+1

@JohnBollinger True. 행렬 연산을 수용적으로 계산하면 다양한 함정이 숨겨집니다. 나는 최대 요소를 찾는 것과 같은 부분 피벗 코드에서 수년간 버그를 가지고 있었고, 코드는'abs()'를 사용하고 올바른'fabs()는 사용하지 않았고, 경고가 불충분했다. 오류는 모든 요소 | 1.0 미만이었습니다. 0.0으로 나누기가 나중에 발생했습니다. – chux

+0

'(1.0 * DBL_EPSILON)'의 ​​요점은 무엇입니까? 하나를 곱하면 실제로 아무 것도 할 수 있습니까? – rici