Inconsistent results (C)?

2019-07-03 00:55发布

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.

标签: c math formula
1条回答
等我变得足够好
2楼-- · 2019-07-03 01:41

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.

查看更多
登录 后发表回答