结果不一致(C)?

结果不一致(C)?,c,math,formula,C,Math,Formula,在这个程序中,我编写了几个公式,对于一个公式,我得到了不一致的结果,尽管每次运行都是相同的代码和输入。所讨论的函数是“WqFormula”。在某些运行中,我得到了正确的结果,即0.041667,而在其他运行中,我得到了0.000000。我使用GCC4.6.3在Ubuntu(64位)上编译。另一件事是,我尝试在pc上使用GCC4.4.6编译和运行这个公式,它给了我每个公式完全不同的结果。代码如下: float PoFormula(float, float, int); float LFormula

在这个程序中,我编写了几个公式,对于一个公式,我得到了不一致的结果,尽管每次运行都是相同的代码和输入。所讨论的函数是“WqFormula”。在某些运行中,我得到了正确的结果,即0.041667,而在其他运行中,我得到了0.000000。我使用GCC4.6.3在Ubuntu(64位)上编译。另一件事是,我尝试在pc上使用GCC4.4.6编译和运行这个公式,它给了我每个公式完全不同的结果。代码如下:

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;
}
float公式(float,float,int);
浮点L公式(浮点,浮点,整数);
浮点WFormula(浮点,浮点,整数);
浮点LQ公式(浮点,浮点,整数);
浮点WQ公式(浮点,浮点,整数);
int main()
{
int n,m;//到达人数,服务频道数量
float mu,lambda;//已服务的平均值,在时间段内到达
printf(“lambda(l)=”);
扫描频率(“%f”和λ);
printf(“mu(m)=”);
scanf(“%f”、&mu);
printf(“m(m)=”);
scanf(“%i”、&m);
浮动测试,测试2,测试3,测试4,测试5;
试验=Po公式(λ,μ,m);
printf(“POF公式为%f\n”,测试);
test2=LFormula(λ,μ,m);
printf(“LFormula是%f\n”,test2);
test3=WFormula(λ,μ,m);
printf(“WFormula是%f\n”,test3);
test4=LqFormula(λ,μ,m);
printf(“LqFormula是%f\n”,test4);
test5=WqFormula(λ,μ,m);
printf(“WqFormula是%f\n”,test5);
返回;
}
浮点PoFormula(浮点λ、浮点μ、整数m)
{
浮点求和,阶乘=1;
int i,j;
对于(i=0;i<(m);i++)
{
对于(j=1;j<(i+1);j++)阶乘*=j;
阶乘=1/阶乘;
阶乘=阶乘*功率((λ/μ),i);
总和+=阶乘;
}
阶乘=1;
对于(j=1;j<(m+1);j++)阶乘*=j;
阶乘=1/阶乘;
阶乘=阶乘*功率((λ/μ),m);
阶乘=阶乘*((m*mu)/(m*mu)-lambda);
阶乘+=求和;
阶乘=1/阶乘;
收益因子;
}
浮点L公式(浮点λ、浮点μ、整数m)
{
浮动因子=1,po;
int j;
po=po公式(λ,μ,m);
对于(j=1;j<(m);j++)阶乘*=j;
阶乘*=pow(((m*mu)-lambda),2);
阶乘=((λ*μ)*(pow((λ/μ),m))/factorial)*po;
阶乘+=(λ/μ);
收益因子;
}
浮点WFormula(浮点lambda、浮点mu、整数m)
{
浮点阶乘=LFormula(λ,μ,m);
阶乘/=λ;
收益因子;
}
浮点数LQ公式(浮点数λ、浮点数μ、整数m)
{
浮点阶乘=LFormula(λ,μ,m);
阶乘-=(λ/亩);
收益因子;
}
浮点WQ公式(浮点λ、浮点μ、整数m)
{
浮点阶乘=LqFormula(λ,μ,m);
阶乘/=λ;
收益因子;
}
每次应打印的内容如下:

Po公式为0.500000

L公式为0.750000

W公式为0.375000

LQ公式为0.083333

WQ公式为0.041667


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

以下函数使用
求和
而不初始化它:

float PoFormula(float lambda, float mu, int m)
{
  float summation, factorial = 1;
  for (i=0; i < (m); i++)
  {
    // ....
    summation += factorial;
  }
float-po公式(float-lambda、float-mu、int-m)
{
浮点求和,阶乘=1;
对于(i=0;i<(m);i++)
{
// ....
总和+=阶乘;
}
因此,您不能期望此函数的任何结果有意义

如果您要求编译器(而且您真的应该这样做!),编译器可以警告您此类问题:

对于GCC,使用编译(我个人也使用
-pedantic
,YMMV)获得尽可能多的警告。然而,在这种特殊情况下,GCC似乎对问题视而不见,直到您使用
-O

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


GCC的未初始化变量分析有两种不同的检查——“明确使用的未初始化”和“可能使用的未初始化”。根据是否启用优化,分析的工作方式不同:

  • 如果优化处于关闭状态(
    -O0
    ,默认),编译器将在一次分析过程中执行这两项检查
  • 如果启用了优化,编译器将执行两个过程-第一个过程仅执行“绝对未初始化”检查,第二个过程在优化后进行(因为优化可能会更改控制流),并执行两个检查
我对GCC内部没有足够的了解,不知道如何在代码中隐藏这个问题,但我将其简化为,如果有人想深入挖掘的话。如果展开循环,即使没有
-O
,也会得到警告,因此循环展开优化可能与此有关



如果您使用MSVC,请使用进行编译以获得最多警告。MSVC在默认警告级别将此未初始化变量报告为问题,无论是否进行优化。

您使用哪些特定输入进行测试?是否使用double而不是float进行此操作?是否与精度相关?在
PoFormula
浮点求和中
使用时没有初始化。奇怪的是,MSVC 2010报告它是一个问题,GCC(mingw-4.6.2)没有。只是比我快。叮当声静态分析器也发现了这个错误。@AlexeyFrunze:不知道为什么,但是使用
-O
或默认的
-O0
以外的任何其他优化级别都会捕获它。非常感谢!这对解决未来的问题非常有帮助。