问题
In this program, I have coded in several formulae and for one formula I am getting inconsistent results, albeit it's the same code and inputs for every run. The function in question is "WqFormula". On some runs I get the correct result which is 0.041667 and on other runs I get 0.000000. I am compiling on Ubuntu (64-bit) using GCC 4.6.3. Another thing is I tried compiling and running this on a pc using GCC 4.4.6 and it gave me completely different results for every formula. Heres the code:
float PoFormula(float, float, int);
float LFormula(float, float, int);
float WFormula(float, float, int);
float LqFormula(float, float, int);
float WqFormula(float, float, int);
int main()
{
int n, m; //# of arrivals, # of service channels
float mu, lambda; //avg serviced, arrivals in time period
printf("lambda (l) = ");
scanf ("%f", &lambda);
printf("mu (m) = ");
scanf ("%f", &mu);
printf("m (M) = ");
scanf("%i", &m);
float test, test2, test3, test4, test5;
test = PoFormula(lambda, mu, m);
printf("PoFormula is %f\n", test);
test2 = LFormula(lambda, mu, m);
printf("LFormula is %f\n", test2);
test3 = WFormula(lambda, mu, m);
printf("WFormula is %f\n", test3);
test4 = LqFormula(lambda, mu, m);
printf("LqFormula is %f\n", test4);
test5 = WqFormula(lambda, mu, m);
printf("WqFormula is %f\n", test5);
return;
}
float PoFormula(float lambda, float mu, int m)
{
float summation, factorial = 1;
int i, j;
for (i=0; i < (m); i++)
{
for (j=1; j < (i+1); j++) factorial *= j;
factorial = 1 / factorial;
factorial = factorial * pow ((lambda/mu), i);
summation += factorial;
}
factorial = 1;
for (j=1; j < (m+1); j++) factorial *= j;
factorial = 1 / factorial;
factorial = factorial * pow ((lambda/mu), m);
factorial = factorial * ((m*mu)/((m*mu) - lambda));
factorial += summation;
factorial = 1 / factorial;
return factorial;
}
float LFormula(float lambda, float mu, int m)
{
float factorial = 1, po;
int j;
po = PoFormula(lambda, mu, m);
for (j=1; j < (m); j++) factorial *= j;
factorial *= pow(((m*mu) - lambda), 2);
factorial = (((lambda*mu)*(pow((lambda/mu),m)))/factorial) * po;
factorial += (lambda/mu);
return factorial;
}
float WFormula(float lambda, float mu, int m)
{
float factorial = LFormula(lambda, mu, m);
factorial /= lambda;
return factorial;
}
float LqFormula(float lambda, float mu, int m)
{
float factorial = LFormula(lambda, mu, m);
factorial -= (lambda/mu);
return factorial;
}
float WqFormula(float lambda, float mu, int m)
{
float factorial = LqFormula(lambda, mu, m);
factorial /= lambda;
return factorial;
}
What should be printing every time is this:
PoFormula is 0.500000
LFormula is 0.750000
WFormula is 0.375000
LqFormula is 0.083333
WqFormula is 0.041667
I'll be glad to provide more information if need be.
回答1:
The following function uses summation
without initializing it:
float PoFormula(float lambda, float mu, int m)
{
float summation, factorial = 1;
for (i=0; i < (m); i++)
{
// ....
summation += factorial;
}
So you cannot expect any results of this function to be meaningful.
Your compiler can warn you about problems like this, if you ask it to (and you really should!):
For GCC, compile with -Wall -Wextra (personally, I also use -pedantic
, YMMV) to get as many warnings as possible. However, in this particular case GCC seems to be blind to the problem until you enable optimization using -O
.
You can stop reading now and simply use -Wall -Wextra -O
when compiling to catch this problem.
GCC's uninitialized variable analysis has two different checks - "definitely used uninitialized" and "possibly used uninitialized". The analysis works differently depending on whether optimization is enabled:
- If optimization is off (
-O0
, default), the compiler performs both checks in a single analysis pass. - If optimization is on, the compiler performs two passes instead - the first pass performs only the "definitely uninitialized" check, the second one happens after optimization (because optimization could change the control flow) and performs both checks.
I don't have enough familiarity with the GCC internals to see what happens to hide this problem in your code, but I reduced it to this test case, if anyone wants to dig deeper. If you unroll the loop, you get the warning even without -O
, so loop unrolling optimizations might have something to do with it.
If you use MSVC, compile with /W4 to get the most warnings. MSVC reports this uninitialized variable as a problem at the default warning level, both with and without optimization.
来源:https://stackoverflow.com/questions/12550115/inconsistent-results-c