2013-02-28 1 views
0

x86 컴퓨터의 우분투 12.04 및 g ++ 4.6.3에서 Matlab 2010을 사용하고 있습니다. 내가 생산과 입력 어떻게 입니다 :matlab 및 C++ 매트릭스 제품 : 동일한 입력, 다른 출력

#include <Src/Tools/Math/Matrix_nxn.h> 
    #include <iostream> 
    using namespace std; 
    int main() 
    { 
     Matrix_nxn<double,4> A1,A2,Tb,aa; 
     A1[0][0] = 0.99958087959447828; A1[0][1] = 1.7725781974830023e-18;A1[0][2] = 0.028949354900049871; A1[0][3] = 0; 
     A1[1][0] = -0.028949354900049871; A1[1][1] = 6.1204654815537932e-17;A1[1][2] = 0.99958087959447828; A1[1][3] = 0; 
     A1[2][0] = 0,   A1[2][1] = -1;   A1[2][2] = 6.1230317691118863e-17;A1[2][3] = 0.21129000000000001; 
     A1[3][0] = 0,   A1[3][1] = 0;   A1[3][2] = 0;    A1[3][3] = 1; 

     A2[0][0] = 0.90634806393366396; A2[0][1] = -0.42253187690835708;A2[0][2] = 0;A2[0][3] = 0; 
     A2[1][0] = 0.42253187690835708; A2[1][1] = 0.90634806393366396; A2[1][2] = 0;A2[1][3] = 0; 
     A2[2][0] = 0;   A2[2][1] = 0;   A2[2][2] = 1;A2[2][3] = 0; 
     A2[3][0] = 0;   A2[3][1] = 0;   A2[3][2] = 0;A2[3][3] = 1; 

     Tb[0][0] = 0.99956387949834924; Tb[0][1] = -0.00016363183229951183; Tb[0][2] = -0.029530052943282908; Tb[0][3] = 0; 
     Tb[1][0] = 0;   Tb[1][1] = 0.99998464792303143; Tb[1][2] = -0.0055411116439683869;Tb[1][3] = 0; 
     Tb[2][0] = 0.029530506297888514;Tb[2][1] = 0.0055386950515785164; Tb[2][2] = 0.99954853411673616; Tb[2][3] = 0; 
     Tb[3][0] = 0;   Tb[3][1] = 0;   Tb[3][2] = 0;    Tb[3][3] = 1; 


    aa = Tb*A1*A2; 
    cout.precision(25); 
    cout <<aa[0][0]<<' '<<aa[0][1]<<' '<<aa[0][2]<<' '<<aa[0][3]<<endl 
     <<aa[1][0]<<' '<<aa[1][1]<<' '<<aa[1][2]<<' '<<aa[1][3]<<endl 
     <<aa[2][0]<<' '<<aa[2][1]<<' '<<aa[2][2]<<' '<<aa[2][3]<<endl 
     <<aa[3][0]<<' '<<aa[3][1]<<' '<<aa[3][2]<<' '<<aa[3][3]<<endl; 
} 

을하고이 operator*의 정의입니다 :

Matrix_nxn<T, N> res; 
size_t i, j, k; 
for (i = 0; i < N; ++i) 
{ 
    for (j = 0; j < N; ++j) 
    { 
    for (k = 0; k < N; ++k) 
    { 
     res[i][j] += m1[i][k] * m2[k][j]; 
    } 
    if (MVTools::isNearInf(res[i][j])) 
    { 
     if (MVTools::isNearPosInf(res[i][j])) 
     throw MVException(MVException::PosInfValue); 
     else 
     throw MVException(MVException::NegInfValue); 
    } 
    } 
} 
return res; 

이상한 것은 내가 MATLAB 및 I 안에 같은 값으로 같은 행렬을 만드는 것입니다 다른 결과를 얻는다. 다음은 Matlab 코드입니다.

Tb = [0.99956387949834924,-0.00016363183229951183,-0.029530052943282908,0;0,0.99998464792303143,-0.0055411116439683869,0;0.029530506297888514,0.0055386950515785164,0.99954853411673616,0;0,0,0,1]; 
A1 = [0.99958087959447828,1.7725781974830023e-18,0.028949354900049871,0;-0.028949354900049871,6.1204654815537932e-17,0.99958087959447828,0;0,-1,6.1230317691118863e-17,0.21129000000000001;0,0,0,1]; 
A2 = [0.90634806393366396,-0.42253187690835708,0,0;0.42253187690835708,0.90634806393366396,0,0;0,0,1,0;0,0,0,1]; 
aa = Tb*A1*A2; 
aa - aaa 

ans = 

    1.0e-16 * 

       0 -0.555111512312578     0     0 
       0     0     0     0 
       0     0     0     0 
       0     0     0     0 

aaa는 C++ 구현의 출력입니다. 오류가 너무 작다는 것을 알고 있지만 문제의 원인을 알고 싶습니다! 많은 코드를 디버깅하고 싶고 좋은 디버깅을 위해서는 0 차이가 필요합니다.

+0

네를하지만 나는 그것이 어디에서 오는지 알고 싶어! : 당신이 관심이 있다면

참조 – Mohammad

답변

1

C++ 코드에서 25 자리의 정밀도를 기대합니다. double 유형을 사용하는 것은 거의 불가능합니다. long double을 사용하면 더 나은 정밀도를 얻을 수 있지만 25 자리와 같은 음흉은 아닙니다.

참조 : What is the precision of long double in C++?

+0

실제로 계산을 위해 너무 많은 정밀도가 필요하지는 않지만 어떤 오류도 원하지 않습니다! Matlab은 두 번 IEEE 754를 사용하고 동일한 데이터 유형을 사용하기 때문에 알고리즘은 (내가 아는 한) 동일하므로 오류는 어디에서 왔습니까? – Mohammad

+0

매트릭스 곱셈에서 연산을 수행하는 순서를 포함하여 여러 위치에서 오류가 발생할 수 있습니다. 코드를 컴파일하는 방법조차도 결과에 영향을 줄 수 있습니다. x64 용 컴파일은 표준 double (64 비트)을 사용하는 반면 x86은 내부적으로 80 비트를 사용하는 487 코 프로세서 명령어를 사용할 수 있습니다. 이로 인해 가장 낮은 자릿수가 달라질 수 있습니다. – fjardon

+0

+1 : SSE 명령어와 x87 FPU 명령어의 사용은 제 대답에서 고려하지 않은 중요한 포인트입니다. – us2012

2

다른 값에 대한 이유는 (그러나 그것은 수 있습니다 미미)는 MATLAB에서 사용하는 알고리즘과 그렇지 같은 을 점이다.

알고리즘은 간단합니다. O(N^3) 행렬 곱셈. 효율적으로 계산할 수있는 작은 크기의 행렬에 대한 특별한 알고리즘과 O(N^3)보다 나은 점근 적 동작을 갖는 복잡한 알고리즘이 있습니다. 소위 작은 오류의