结果不一致(C)? [英] Inconsistent results (C)?

查看:106
本文介绍了结果不一致(C)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在此程序中,我已编写了多个公式,但对于一个公式,我得到的结果不一致,尽管每次运行都使用相同的代码和输入.有问题的函数是"WqFormula".在某些运行中,我得到的正确结果是0.041667,而在其他运行中,我得到的是0.000000.我正在使用GCC 4.6.3在Ubuntu(64位)上进行编译.另一件事是我尝试使用GCC 4.4.6在PC上编译并运行此程序,它为每个公式提供了完全不同的结果.这是代码:

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;
}

每次都应该打印什么:

PoFormula为0.500000

PoFormula is 0.500000

LFormula为0.750000

LFormula is 0.750000

WFormula为0.375000

WFormula is 0.375000

LqFormula为0.083333

LqFormula is 0.083333

WqFormula为0.041667

WqFormula is 0.041667

如有需要,我很乐意提供更多信息.

I'll be glad to provide more information if need be.

推荐答案

以下函数使用summation而不对其进行初始化:

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!):

对于GCC,请使用 -Wall -Wextra 进行编译(我个人也可以使用-pedantic,YMMV)来获取尽可能多的警告.但是,在这种特殊情况下,直到您启用优化使用-O.

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.

您现在可以停止阅读,只需在编译时使用-Wall -Wextra -O即可解决此问题.

You can stop reading now and simply use -Wall -Wextra -O when compiling to catch this problem.

GCC的未初始化变量分析具有两个不同的检查-"绝对未使用初始化"和"可能未初始化使用".根据是否启用了优化,分析的工作方式有所不同:

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:

  • 如果优化关闭(默认为-O0),则编译器将在一次分析过程中执行两项检查.
  • 如果启用了优化,则编译器将执行两次遍历-第一次遍历仅执行绝对未初始化"检查,第二遍遍在优化之后进行(因为优化可能会更改控制流)并执行两项检查.
  • 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.

我对GCC内部没有足够的了解,无法看到将这个问题隐藏在您的代码中的情况,但是我将其简化为

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.

如果您使用MSVC,请使用 /W4 进行编译最警告.无论是否进行了优化,MSVC都将未初始化的变量报告为默认警告级别的问题.

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.

这篇关于结果不一致(C)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆