计算1+的和;(1/2!)+…+;C语言中的(1/n!)n数字
就像标题所说的,我如何计算n个数的和的形式:1+(1/2!)+⋯(1/n!)?我已经得到了谐波系列的代码:计算1+的和;(1/2!)+…+;C语言中的(1/n!)n数字,c,algorithm,C,Algorithm,就像标题所说的,我如何计算n个数的和的形式:1+(1/2!)+⋯(1/n!)?我已经得到了谐波系列的代码: #include <stdio.h> int main( void ) { int v=0,i,ch; double x=0.; printf("Introduce un número paracalcular la suma: "); while(scanf("%d",&v)==0 || v<=0) {
#include <stdio.h>
int main( void )
{
int v=0,i,ch;
double x=0.;
printf("Introduce un número paracalcular la suma: ");
while(scanf("%d",&v)==0 || v<=0)
{
printf("Favor de introducir numeros reales positivos: ");
while((ch=getchar())!='\n')
if(ch==EOF)
return 1;
}
for (i=v; i>=1; i--)
x+=1./i;
printf("EL valor de la serie es %f\n", x);
getch();
return 0;
}
#包括
内部主(空)
{
int v=0,i,ch;
双x=0。;
printf(“介绍unnúmero paracalcularla suma:”);
而(scanf(“%d”,&v)==0 | | v=1;i--)
x+=1./i;
printf(“系列产品价格%f\n”,x);
getch();
返回0;
}
这里的问题是。。我已经得到了作为分数的和,但是如何使变量“I”成为阶乘呢
注意:我正在用C语言编程,使用DEV-C++4.9.9.2如果您只是想计算前n个阶乘,我建议您只需递归计算它们,例如
factorial[0] = 1;
for (i = 1; i < n; i++) factorial[i] = factorial[i-1] * i;
factorial[0]=1;
对于(i=1;i
但是,除非将它们存储为浮点数,否则大阶乘将很快溢出。对于调和求和1./i+1./(i-1)。。。1./1. 我建议你继续按那个顺序做 [编辑]重写:感谢@pablo197指出了我的错误 要计算谐波和1+(1/2!)+…+(1/n!),请先将最低有效项相加,这样有助于将精度损失降至最低。从最低有效项
1/n
开始为sum
,该项与n-1项之和为:sum=(1+sum)/(n-1)
,依此类推。(见下文)
添加1.0
或1/0
到one\u over\u factorial\u系列
,关于e=2.7182818284…
[编辑]详细信息,显示如何直接n!避免了计算
1 + (1/2!) + … + (1/n!) =
1/n! + 1/((n-1)!) + 1/((n-2)!) + 1/((n-3)!) + ... + 1 =
(1/n + 1)/((n-1)!) + 1/((n-2)!) + 1/((n-3)!) + ... + 1 =
((1/n + 1)/(n-1) + 1)/((n-2)!) + 1/((n-3)!) + ... + 1 =
...
((((1/n + 1)/(n-1) + 1)/(n-2) + 1)/(n-3) + 1)/(n-4) + ... =
数字n!等于n和前面阶乘的乘积,即(n-1)
如果你计算n!在一次迭代中,您正在执行n个产品。
在下一步中,假设n+1,您再次重复这n个乘积,然后再乘以n+1。
这意味着您正在一次又一次地重复相同的操作 更好的策略是保持在步骤n中计算的前一个阶乘,然后在步骤n+1中,仅乘以n!n+1。这将每次迭代中的产品数量减少到1个 因此,可以按以下方式计算序列:
int max_n = 20; /* This value can come from another point of the program */
int n; /* Initial value of the index */
double factorial_n = 1; /* It has to be initialized to 1, since the factorial of 0 is 1 */
double sum = 0.0; /* It has to be initialized to 0, in order to calculate the series */
for (n = 0; n <= max_n; )
{
sum += 1.0/factorial_n;
n++;
factorial_n *= n;
}
printf("Series result: %.20f\n", sum);
int max_n=20;/*该值可以来自程序的另一个点*/
int n;/*索引的初始值*/
双阶乘n=1;/*它必须初始化为1,因为0的阶乘是1*/
双和=0.0;/*必须将其初始化为0才能计算序列*/
对于(n=0;n在这种情况下计算阶乘是不好的,因为它会导致n的小值溢出。使用以下伪代码将其放入O(n)
中而不溢出
double sum = 0.0;
double acc = 1;
double error = 0.0000001;
for(i=1;i<=n;i++) {
acc = acc/i;
if(acc<error)
break;
sum = sum + acc;
}
print(sum);
注意:-因为上面的方法是反向构建的,所以它更精确,但不幸的是,因为它是O(N),所以更耗时即使对于更高的值,由于阶乘函数增长非常快,因此精度的提高也可以忽略不计,因此误差持续快速减小。垂直选项卡?请…为阶乘创建一个函数。如何从1..N生成一个系列?使用它来将1!
的项设置为N!
但只需将其倒置即可。这就是思考阶乘的含义,然后写一个函数来完成它。然后输入i.@KerrekSB exp(1)是ans if n->infinity因此小n的精度损失,如5-1:OP问题是关于指数级数的。您的代码有一个从未使用过的伪阶乘计算,最终结果是谐波级数,OP已经解决了。@pablo1977对。Face palm-需要重新工作。我省略了我的dow请注意,因为您现在获得了正确的结果,但我一点也不相信。您的解决方案对我来说不太清楚。@pablo1977添加了一些细节,说明“1+(1/2!)+…+(1/n!)”如何更改为“(((1/n+1)/(n-1)+1)/(n-2)+1/(n-3)+1/(n-4)+…”。好的。我喜欢您的想法。首先,我不相信它,因为它“抽象地”很好,但在实践中可能会因分段累积误差而失去准确性。然而,我比较了您的版本和我的版本,两者给出了完全相同的结果(关于
中的exp(1)
)。关于效率,您的算法的运算次数似乎与我的相同(n*(1减量+1除法+1和+1赋值))。但是,我发现“在数组中存储阶乘”技术的速度更快.我无法解释差异,但它似乎并不重要。这与其说是一个递归解决方案,不如说是一个动态规划解决方案。然而,该算法快速而准确。@pablo1977 factorial将溢出较大的值,并给出不可预测的值,为什么不除以数字,而至少乘以较高的值呢e 0,不会产生副作用。@Vikramhat:我避免在每次迭代中被j除,因为这会带来数值问题。另一方面,整数的乘积是精确的,正如您所指出的,只需注意溢出。我认为溢出处理将使我的论述变得模糊。不过,有一点评论可以添加。@pablo1977,由于您应用的模糊处理导致算法既不快速也不准确,我坚持认为这是一种糟糕的编码练习。打代码高尔夫很少会提高执行速度,但通常会降低试图理解代码的人的脑速。@Richard:“很少”不适用于我的代码,因为它的速度和准确性取决于“操作”的方式。我可以接受你对“风格”的批评,但你判断速度和准确性是错误的,因为你没有对问题进行必要的数学分析
#include <stdio.h>
#define MAX_N 100
double factorial[MAX_N+1];
void build_factorials(double *factorial, int max)
{
factorial[0] = 1.0;
for (int j = 0; j <= max; )
{
j++;
factorial[j] = factorial[j-1] * j;
}
}
double exp_series(int n)
{
int j;
double sum;
if (n > MAX_N) /* Error */
return 0.0;
sum = 0.0;
for (j = n; j >= 0; j--)
sum += 1.0/factorial[j];
return sum;
}
int main(void)
{
int n;
double sum;
build_factorials(factorial, MAX_N);
printf("Series (up to n == 11): %.20f\n", exp_series(11));
printf("Series (up to n == 17): %.20f\n", exp_series(17));
printf("Series (up to n == 9): %.20f\n", exp_series(9));
getchar();
}
double sum = 0.0;
double acc = 1;
double error = 0.0000001;
for(i=1;i<=n;i++) {
acc = acc/i;
if(acc<error)
break;
sum = sum + acc;
}
print(sum);
double sum = 0.0;
double acc = 1;
for(i=n;i>=1;i--) {
sum = (sum + 1)/i;
}
print(sum);