2013-05-27 5 views
1

이것은 며칠 동안 매우 혼란 스러웠습니다. 나는 C 언어에 다소 익숙하지만 일반적으로 인터넷 검색으로 상황을 파악할 수는 있지만 이것은 저를 곤혹스럽게합니다. 나는 몇몇 사람들에게 물었고 그들은 나를 도울 수 없었다.호출 함수는 두 가지 다른 출력 값을 제공합니다.

문제점은 코드 (48 및 49)에 표시된 행을 포함 시키면 수학적으로 같아야하지만 f1은 output2와 다른 출력을 계산한다는 것입니다. 그러나, 내가 다른 방식으로 그것을 부르면, 나는이 문제를 가지지 않는다. 나는 우분투 12.04에서 gcc 나 g ++로 컴파일하고있다. 둘 다 같은 문제를 안고있다.

코드도 pastebin에 업로드했습니다. 문제는 48 번과 49 번 라인을 참조하십시오.

미리 도움을 주셔서 감사합니다. 하드의

#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 

#define PARAMETER1 100 
#define nx1 5 
#define nx2 10 
#define nx3 10 
#define ny1 4 
#define ny2 5 
#define ny3 10 
#define Nx nx1+nx2+nx3+1 
#define Ny ny1+ny2+ny3+1 
#define X1_LENGTH 5.0  
#define X2_LENGTH 10.0 
#define X3_LENGTH 50.0 
#define Y1_LENGTH 0.04 
#define Y2_LENGTH 5.0 
#define Y3_LENGTH 20.0 

double f(int j,int i); 
double g(int j,int i); 
double dx(int i); 
double calc_value_pos(int i); 
double calc_value_neg(int i); 
double **matrix; 
double f1(int j,int i); 
double calc_value2_pos(int i); 
double calc_value2_neg(int i); 
double f2(int j,int i); 

int main(void){ 

    matrix=(double **)malloc((size_t) ((Ny+1)*(Nx+1)+1)*sizeof(double *)); 
    for (int j=1; j<=(Ny+1)*(Nx+1); j++) { 
     matrix[j] = (double *)malloc((size_t) ((Ny+1)*(Nx+1)+1)*  sizeof(double)); 
    } 

    for (int j=1; j<=Ny+1; j++){ 
     for (int i=1; i<=Nx+1; i++){ 
      matrix[j][i]=0.0; 
     } 
    } 

    for (int i=0; i<=Nx; i++){ 
     for (int j=0; j<=Ny; j++){ 
      int k=i+(j)*(Nx+1)+1; 
      matrix[k][k] = f(j,i);  /*including this line causes the problem*/ 
      //matrix[k][k] = f1(j,i);  /* including this line does not cause the problem*/ 
     } 
    } 
    return 1; 
} 

double f(int j, int i){ 
    double output=f1(j,i)+f2(j,i); 
    return output; 
} 
double f1(int j, int i){ 
    double output; 
    if (i==0 || j==0 || i==Nx || j==Ny) output=0.0; 
    if (i!=0 && j!= 0 && i!= Nx && j!=Ny) { 
     output = (g(j,i)*g(j,i+1))/(g(j,i)*calc_value_pos(i)+g(j,i+1)*calc_value_neg(i)); 
     double output2; 
     output2=1.0/((calc_value_neg(i)/g(j,i)) + (calc_value_pos(i)/g(j,i+1))); 
     /*if (output2!=output2) printf("output2: %lf\n",output2);*/ 
     if (output != output2 && output==output) printf("(j%d,i%d) output:%lf \toutput2:%lf\n",j,i,output,output2); 
    } 
    if (output!=output) output=0.0; 
    return output; 
} 

double f2(int j,int i){ 
    /* calculates f2 for (j,i) */ 
    double output; 
    if (j==0 || i==0) output=0.0; 
    else output = g(j,i)*g(j,i-1)/(g(j,i)*calc_value2_neg(i)+g(j,i-1)*calc_value2_pos(i)); 
    if (output!=output) output=0.0; 
    return output; 
} 

double calc_value2_pos(int i){ 
    /* calculates calc_value2_pos for X=i */ 
    double output= dx(i)/2.0; 
    return output; 
} 

double calc_value2_neg(int i){ 
    /* calculates calc_value2_neg for X=i */ 
    if (i==0) printf("Warning off grid\n"); 
    double output= dx(i-1)/2.0; 
    return output; 
} 

double g(int j,int i){ 
    double output=PARAMETER1; 
    if (j==0 || i==0) output=0.0; 
    if (j>=ny1+1 && j<=ny1+ny2 && i>=1 && i<=nx1) output=0.0; 
    if (output!=output) printf("calc_D(%d,%d) error: output==nan\n",j,i); 
    return output; 
} 

double calc_value_pos(int i){ 
    if (i==Nx) printf("Warning east pos\n"); 
    double output; 
    output = dx(i+1)/2.0; 
    if (output!=output) printf("calc_delta_e_pos(%d) error: output==nan\n",i); 
    return output; 
} 

double calc_value_neg(int i){ 
    double output=dx(i)/2.0; 
    if (output!=output) printf("calc_delta_e_neg(%d) error: output==nan\n",i); 
    return output; 
} 

double dx(int i){ 
    double output; 
    if (i<=nx1) output=1.0*X1_LENGTH/nx1; 
    if (i<=nx1+nx2 && i>=nx1+1) output=1.0*X2_LENGTH/nx2; 
    if (i<=nx1+nx2+nx3 && i>=nx1+nx2+1) output=1.0*X3_LENGTH/nx3; 
    if (output!=output) printf("delta_x(%d) error: output==nan\n",i); 
    return output; 
} 
+0

이것이 C++ 태그가 지정된 이유가 있습니까? –

+0

중요한 경우, C 또는 C++ 컴파일러를 사용하고 있습니까? – pmg

+0

C와 C++ 둘 다 사용하여 C++로 태그를 붙였습니다. – Ben

답변

0

종류는이 코드가 무엇을하고 있는지 알아낼 수 있지만합니다 :

output = (g(j,i)*g(j,i+1))/(g(j,i)*calc_value_pos(i)+g(j,i+1)*calc_value_neg(i)); 
output2= 1.0/((calc_value_neg(i)/g(j,i)) + (calc_value_pos(i)/g(j,i+1))); 

그것은 이러한 수학적 유사해야하는 이유를 나에게 분명하다. output2

1.0/((calc_value_neg(i)/g(j,i)) + (calc_value_pos(i)/g(j,i+1))); 

에서 그래서 우리는 공통 분모 얻기 위해 다중 교차 : 분수로 나누어

1.0/ ((g(j,i+1)*(calc_value_neg(i)) + (g(j,i)*(calc_value_pos(i)))/(g(j,i)*g(j,i+1)) 

1.0 동일을 상호 그 부분의 :

g(j,i)*g(j,i+1)/(g(j,i+1)*calc_value_neg(i) + g(j,i)*(calc_value_pos(i))) 

정확히입니다 출력과 동일 :

g(j,i)*g(j,i+1)/(g(j,i)*calc_value_pos(i) + g(j,i+1)*calc_value_neg(i)) 

코드를 나타내는 방법에 오류가 없으므로 계산 자체의 어딘가에서 발생합니다. 나는 디버깅을위한 내 머리에 코드의 전체 블록을 얻을 수 있지만, 두 가지 표면에 뛰어 : F2에서

  1. g(j,i-1)
  2. f()f()f1() 같은 것, f1()+f2()입니다 f2()이 확실히 0과 같지 않으면?

계산을 수행하기 전에 1.0을 double로 직접 캐스팅 했습니까? 나는 (C가 아님에도 불구하고) 전에는 1.0과 비슷한 것을 썼다. 컴파일러는 double 대신에 float으로 처리했고, 계산은 double로 캐스팅되기 전에 발생하고 라운딩을 얻는다. 오류. 이 던지는

시도 :

double one_d = 1.0; 
output2= one_d/((calc_value_neg(i)/g(j,i)) + (calc_value_pos(i)/g(j,i+1))); 

그냥 종달새는, 미안 내가 더 좋은 생각이 없습니다. calc_value_pos에서

+0

문제는 f1! = f가 아닙니다. 문제는 output! = output2입니다. 나는 그것이 어떻게 부르는지에 따라 왜 그것이 일어나는 지 이해하지 못합니다. f에서 f1이 호출되면! = output2를 출력합니다. f가 주 출력 == output2에서 호출 될 때. – Ben

+0

그게 내 문제를 해결했을 때도 output3으로 설정했을 때 (즉, 내가 output3에 출력 한 것을 설정하면 output == output2가됩니다.) 왜 이런 일이 일어날 수 있는지에 대한 아이디어는 무엇입니까? – Ben

+0

왜 1.0이 전송되지 않는지 이해합니다. 제대로 계산하면 잘못된 값을 얻을 수는 있지만 왜 모든 수학 연산이 두배로 끝날 때 출력이 이어지지 않습니까? – Ben

3

, i == 25를 들어, dx(26) 전화 :

double dx(int i){ 
    double output; 
    if (i<=nx1) output=1.0*X1_LENGTH/nx1; 
    if (i<=nx1+nx2 && i>=nx1+1) output=1.0*X2_LENGTH/nx2; 
    if (i<=nx1+nx2+nx3 && i>=nx1+nx2+1) output=1.0*X3_LENGTH/nx3; 
    if (output!=output) printf("delta_x(%d) error: output==nan\n",i); 
    return output; 
} 

지금, 26 > nx1 + nx2 + nx3는, 그래서 당신은 정의되지 않은 동작을 의미 초기화되지 않은 변수를 반환합니다.

+0

감사합니다 !! 나는 그것을 놓쳤다 고 믿을 수 없습니다. 정말 고마워요! 그래서 서로 다른 컴파일러가 정의되지 않은 행동을 다르게 대하고있었습니다. 다른 방식으로 함수를 호출하는 것은 정의되지 않았기 때문에 다른 결과를 나타 냈습니다. 이해가 되나요? – Ben

+0

결국 UB라고 할 수는 없지만 proba bly, dx가 호출 될 때'output'이 할당 된 곳에 다른 호출 순서가 다른 값을 남겼습니다. (그리고 리눅스와 윈도우에 대한 다른 호출 규칙은 분명히 윈도우에 나타나지 않게 만들었다.) –

+0

그런 종류의 의미가있다. 이것이 C가 수학을하는 방식을 이해하지 못했기 때문에 이것이 다소 복잡한 문제라고 생각했습니다. 내가 놓친 버그 야. 도와 줘서 고마워 !! – Ben

관련 문제