2013-05-27 3 views
1

Это меня очень смутило в течение нескольких дней. Я немного новичок в C, но, как правило, я могу понять, что такое googling, но это меня озадачило. Я спросил несколько человек, и они не смогли мне помочь.вызывающие функции дают 2 разных значения вывода

Проблема заключается в том, что когда я включаю строку, отмеченную в моем коде (48 и 49), f1 вычисляет выходной результат, отличный от output2, хотя они должны быть математически одинаковыми. Однако, если я называю это по-другому, у меня нет этой проблемы. Я компилирую на ubuntu 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)) 

Таким образом, ошибка не в том, как вы представляете код, это происходит где-то в самом вычислении. Я не могу получить весь этот блок кода в моей голове для отладки, но 2 вещи выскочила на поверхности:

  1. g(j,i-1) в f2
  2. f() является f1()+f2(), так почему бы f() быть такой же, как f1() если f2() определенно приравнивается к нулю?

Вы пробовали напрямую с использованием 1.0 в качестве двойника перед выполнением расчета? Я столкнулся с проблемами до (хотя и не в C), где я написал что-то вроде 1.0, и обработан компилятором как 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))); 

Просто жаворонком, жаль у меня нет никаких идей лучше.

+0

Проблема не в том, что f1! = F. Проблема в том, что output! = Output2. Я не понимаю, почему это происходит в зависимости от того, как я это называю. Когда f1 вызывается из f, тогда выведите выходной сигнал = output2. Когда f вызывается из основного вывода == output2. – 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 в конце концов, но proba bly, различные вызывающие последовательности, только что сделанные разными значениями, останутся там, где 'output' был выделен при вызове' dx'. (И разные соглашения о вызовах на linux и Windows не отображались в Windows, по-видимому.) –

+0

Хорошо, что это имеет смысл. Я думал, что это была сложная проблема, потому что я не понимал, как C делает математику. Оказывается, это ошибка, которую я пропустил. Большое спасибо за Вашу помощь!! – Ben

Смежные вопросы