结果不一致(C)? [英] Inconsistent results (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屋!