不一致的结果(C)?(Inconsistent results (C)?)

2019-09-22 19:57发布

在这个程序中,我已经编写的几个公式和一个公式我得到不一致的结果,尽管它每次运行相同的代码和投入。 有问题的功能是“WqFormula”。 在某些运行我得到正确的结果是0.041667和其他运行我得到0.000000。 我使用GCC 4.6.3在Ubuntu(64位)编译。 另一件事是我试图编译和使用GCC 4.4.6在PC上运行这一点,它给了我所有的公式完全不同的结果。 继承人的代码:

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

LFormula是0.750000

WFormula是0.375000

LqFormula是0.083333

WqFormula是0.041667

我会很乐意提供如果需要更多的信息。

Answer 1:

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

float PoFormula(float lambda, float mu, int m)
{
  float summation, factorial = 1;
  for (i=0; i < (m); i++)
  {
    // ....
    summation += factorial;
  }

所以,你不能指望这个功能的任何结果才有意义。

你的编译器可以警告你这样的问题,如果你要求它(和你真的应该!):

对于GCC,编译-Wall -Wextra (个人而言,我也用-pedantic ,情况因人而异),以获得尽可能多的警告越好。 然而,在这种特殊情况下GCC似乎直到你是盲目的问题能够优化使用-O

您现在可以停止阅读,只需使用-Wall -Wextra -O编译赶上这个问题的时候。


GCC的未初始化的变量分析,有两种不同的检查- “ 肯定使用的未初始化”和“ 可能使用的未初始化”。 分析作品不同,这取决于优化是否启用:

  • 如果优化是关闭( -O0 ,默认值),编译器执行在一次分析中通两个检查。
  • 如果优化时,编译器执行两次传球,而不是 - 第一遍只执行了“绝对未初始化”检查,优化后的第二个情况(因为优化可以改变控制流),执行两种检查。

我没有与海合会内部足够的熟悉,看看会发生什么藏在你的代码这个问题,但我把它降低到本次测试的情况下 ,如果有人想进行深入分析。 如果您展开循环,你会得到警告,即使没有-O ,所以循环展开优化可能有一些用它做。


如果您使用的MSVC,编译/W4得到最警告。 MSVC报告这个未初始化的变量作为默认的警告级别的问题,既没有优化。



文章来源: Inconsistent results (C)?
标签: c math formula