该程序询问用户掷硬币的次数(n;试验次数)。
成功被视为头脑。
完美无缺,程序会创建一个介于0和1之间的随机数.0被认为是头和成功。
然后,程序应该输出获得x个头数的预期值。例如,如果硬币被翻转4次,那么使用公式
的概率如下nCk * p^k * (1-p)^(n-k)
Expected 0 heads with n flips: xxx
Expected 1 heads with n flips: xxx
...
Expected n heads with n flips: xxx
当使用“更大”的数字执行此操作时,数字会出现奇怪的值。如果将15或20放入输入中,则会发生这种情况。我得到0和负值的值应为xxx。
调试,我注意到nCk已经出现负面而且对于较高的值不正确而且相信这是问题。我将这个公式用于我的组合:
double combo = fact(n)/fact(r)/fact(n-r);
这是我的事实函数的伪代码:
long fact(int x)
{
int e; // local counter
factor = 1;
for (e = x; e != 0; e--)
{
factor = factor * e;
}
return factor;
}
有什么想法?我的猜测是我的阶乘或组合函数超过最大值或其他东西。
答案 0 :(得分:1)
您尚未提及factor
如何声明。我认为你正在获得整数溢出。我建议你使用双倍。这是因为由于您正在计算期望值和概率,因此您不应过多关注精度。
尝试将您的事实功能更改为。
double fact(double x)
{
int e; // local counter
double factor = 1;
for (e = x; e != 0; e--)
{
factor = factor * e;
}
return factor;
}
编辑: 另外,要计算nCk,您无需计算3次因子。您可以通过以下方式简单地计算此值。
if k > n/2, k = n-k.
n(n-1)(n-2)...(n-k+1)
nCk = -----------------------
factorial(k)
答案 1 :(得分:1)
你超过了长期的最大值。因子增长如此之快,以至于你需要正确的数字类型 - 这取决于你需要什么样的价值。
Long是有符号整数,一旦传递2 ^ 31,该值将变为负数(它使用2的补码数学)。
使用unsigned long会给你一点时间(一点多),但对于阶乘,它可能不值得。如果您的编译器支持long long,那么请尝试“unsigned long long”。那将(通常,取决于编译器和CPU)加倍你正在使用的位数。
您也可以尝试切换为使用double。你将面临的问题是随着数字的增加你会失去准确性。 double是浮点数,因此您将拥有固定数量的有效数字。如果您的最终结果是近似值,这可能会正常工作,但如果您需要精确值,则无效。
如果这些解决方案都不适合您,您可能需要使用“无限精度”数学包,您应该可以搜索它。你没有说你是在使用C还是C ++;使用C ++会更加愉快,因为它会提供一个类似数字的类,并且会使用标准的算术运算符。