2013-05-27 116 views
1

這讓我很困惑了幾天。我對C有點新,但通常我可以通過Google搜索來弄清楚,但這讓我很難過。我問過幾個人,他們沒能幫助我。調用函數給出2個不同的輸出值

的問題是,當我包括我標誌着我的代碼(48和49)的線,F1計算輸出從輸出2不同,即使他們應該是數學上是相同的。但是,如果我以不同的方式調用它,那麼我沒有這個問題。我正在使用gcc或g ++編譯Ubuntu 12.04(兩者都提供相同的問題)。

我還上傳代碼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)) 

所以錯誤不在於如何表示代碼,它發生在計算本身的某處。我不能讓這個代碼整個塊到我頭上了調試,但兩件事情跳出表面上:

  1. 在F2 g(j,i-1)
  2. f()f1()+f2(),那麼,爲什麼f()是一樣的f1()除非f2()肯定等於零?

你有沒有嘗試過直接鑄造1.0作爲雙前做計算?我之前遇到過問題(雖然不是C),我寫了類似1.0的東西,編譯器將它視爲float而不是double,然後計算髮生在double之前,並且我得到一個舍入錯誤。

嘗試引發此:

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

只是雲雀,對不起,我沒有什麼更好的想法。

+0

問題不在於f1!= f。問題是輸出!= output2。我不明白爲什麼會發生這取決於我怎麼稱呼它。當在f中調用f1時,輸出!= output2。當從主輸出== output2調用f時。 – Ben

+0

這樣做解決了我的問題,即使當我把它設置爲output3(即當我設置你發佈到output3,output == output2。有關爲什麼會發生這種情況的任何想法? – Ben

+0

我明白爲什麼如果1.0沒有投射正確它會給出錯誤的值,但爲什麼會繼續輸出,當所有的數學完成雙打? – Ben

3

calc_value_pos,爲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

Ahhhhh謝謝!!我不敢相信我錯過了,非常感謝!所以不同的編譯器處理未定義的行爲是不同的以不同的方式調用函數產生了不同的結果,因爲它是未定義的?這有意義嗎? – Ben

+0

我不能絕對確定,畢竟它是UB,但是概率bly,不同的調用序列只是在調用'dx'時將'output'分配給了不同的值。 (並且在Linux和Windows上的不同調用約定使得它在Windows上顯示不出來。) –

+0

好吧,這種說法是有道理的。我認爲這是一個複雜的問題,因爲我不明白C是如何做數學的。原來,這是我錯過的一個錯誤。非常感謝你的幫助!! – Ben

相關問題