这也是一个精度问题的难题(求助)
这串代码输入33以上的值,打印出来的结果就会出错。。为什么呢?题目:
自然常数 e 可以用级数 1+1/1!+1/2!+⋯+1/n!+⋯ 来近似计算。本题要求对给定的非负整数 n,求该级数的前 n+1 项和。
输入格式:
输入第一行中给出非负整数 n(≤1000)。
输出格式:
在一行中输出部分和的值,保留小数点后八位。
输入样例:
10
输出样例:
2.71828180
#include <stdio.h>
int jc(int n);
int main()
{
int e,i;
scanf("%d",&e);
double sum = 0;
for(i = 0;i <= e;i++)
{
sum += 1.0/jc(i);
}
printf("%.8lf",sum);
return 0;
}
int jc(int n)
{
int i,sum = 1;
for(i = 2;i <= n;i++)
{
sum *= i;
}
return sum;
} 本帖最后由 歌者文明清理员 于 2023-5-5 22:17 编辑
[*]问题分析
代码中jc函数计算阶乘使用了int类型,而int类型的最大值是2147483647,当输入n>=33时, jc(n)的结果将超出此范围,因此产生错误结果。为避免此问题,可以考虑使用更大数据类型(如long long)进行计算,或者使用数学公式简化计算。
[*]解决方案:
可以将jc函数中的int类型改为long long类型,如下所示:
long long jc(int n)
{
int i;
long long sum=1;
for(i=2;i<=n;i++)
sum*=i;
return sum;
}
同时需要修改main函数中调用jc函数的部分,变成 1.0/jc(i),以避免出现整数除法计算错误的问题。
完整代码如下:
```
#include <stdio.h>
long long jc(int n);
int main()
{
int e,i;
scanf("%d",&e);
double sum = 0.0;
for(i = 0;i <= e;i++)
{
sum += 1.0/jc(i);
}
printf("%.8lf",sum);
return 0;
}
long long jc(int n)
{
int i;
long long sum = 1;
for(i = 2;i <= n;i++)
{
sum *= i;
}
return sum;
}
```
请注意,这里只是一种可能的修改方法,还可以通过使用数学公式或其他优化方式来避免溢出问题。
本帖最后由 isdkz 于 2023-5-5 22:35 编辑
这段代码在计算阶乘时采用了 int 类型来存储结果。当输入的值大于 33 时,阶乘计算的结果会超过 int 类型的最大值(231 - 1 = 2,147,483,647)。这将导致整数溢出,从而使计算的结果出错。为了避免这个问题,我们可以将阶乘函数的返回值类型改为更大的数据类型,如 long long 或者 double。
同时,我们也需要使用 double 类型的变量进行累乘。这是修改后的代码:
#include <stdio.h>
double jc(int n);
int main()
{
int e, i;
scanf("%d", &e);
double sum = 0;
for (i = 0; i <= e; i++)
{
sum += 1.0 / jc(i);
}
printf("%.8lf", sum);
return 0;
}
double jc(int n)
{
int i;
double sum = 1;
for (i = 2; i <= n; i++)
{
sum *= i;
}
return sum;
}
这样,当输入大于33的数时,计算结果就不会因为整数溢出而出错了。 isdkz 发表于 2023-5-5 22:28
这段代码在计算阶乘时采用了 int 类型来存储结果。当输入的值大于 33 时,阶乘计算的结果会超过 int 类型的 ...
歌者文明清理员 发表于 2023-5-5 22:33
我去,上标复制出来就这样了 isdkz 发表于 2023-5-5 22:34
我去,上标复制出来就这样了
不知道为什么,这个复制到 www.baidu.com 是正常的,一粘贴到论坛就会 歌者文明清理员 发表于 2023-5-5 22:14
[*]问题分析
代码中jc函数计算阶乘使用了int类型,而int类型的最大值是2147483647,当输入n>=33时, j ...
long long我试过了 不行 double行 a905448839 发表于 2023-5-5 23:01
long long我试过了 不行 double行
非常抱歉,我的回答有误。在计算阶乘过程中确实会产生大量的溢出问题,即使使用long long也无法完全避免。
既然如此,我们可以考虑对式子进行改写,以减少计算阶乘的次数,降低溢出的风险。具体来说,我们可以使用浮点数类型来计算 e 的每个小于 1 的正整数幂的倒数(即 1 / i!),并将它们累加到结果中。这样一来,我们就避免了计算i的阶乘,同时能够保证精度。修改后的代码如下:
```
#include <stdio.h>
int main()
{
int e,i;
scanf("%d",&e);
double sum = 0.0;
for(i = 0;i <= e;i++)
{
double item = 1.0;
int j;
for(j = 2;j <= i;j++)
{
item /= j;
}
sum += item;
}
printf("%.8lf",sum);
return 0;
}
```
这样便能够避免溢出问题,同时输出结果也更加精确,是一种比较常见的处理方法。感谢您指出之前回答中的错误。
页:
[1]