[pta随笔]求e的近似值——极限思想、浮点与整形的溢出结算

原题:

自然常数 e 可以用级数 1+1/1!+1/2!+⋯+1/n!+⋯ 来近似计算。本题要求对给定的非负整数 n,求该级数的前 n+1 项和。

输入格式:

输入第一行中给出非负整数 n(≤1000)。

输出格式:

在一行中输出部分和的值,保留小数点后八位。

输入样例:

10

输出样例:

2.71828180

 一开始觉得这题还挺简单的,但是当看到n<=1000的时候心里就咯噔一下了,然而还是硬着头皮按函数的暴力思维写了下代码:

#include<bits/stdc++.h>
using namespace std;
long long sjc(int a)
{
    long long mult=1;
    for(int i=1;i<=a;i++)
    {
        mult*=i;
    }
    return mult;
}
int main()
{
    int n;
    cin>>n;
    double sum=1;
    for(int i=1;i<=n;i++)
    {
        sum+=(double)1/sjc(i);
    }
    printf("%.8lf",sum);
}

运行之后果不其然wa了,检测点3不过检,提示里就是最大n,很明显,爆精度了。

cout<<sjc(999)<<endl;的结果是inf。

然而这道题到底不是难题,高精度虽然也不算难敲,但是这么想的话一定涉及到了高精度浮点数,这样就显得无趣了,所以我去韩了个同学的成品:

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n;
	cin>>n;
	double mult = 1, sum=1;
	for(int i=1; i<=n; i++)
	{
		mult *= i;
		sum += 1.0/mult;
	}
	printf("%.8lf",sum);
	return 0;
}

这其实就是最早的时候,没学函数时候我们的计算方式,结果很明显依然是会爆精度的,但是,它却可以轻而易举的过检测点3。

这到底是为什么呢?我打出了cout<<mult<<endl;编译器输出了0。

本质而言,这道题对于极大的n其实就是简单的无限大与无穷小的思想,1/inf无限小,对于1/999!的宏伟数据来说,哪怕很唬人的给了个保留8位小数,依然是无济于事的。

然而我后面再在错题上缝补了一下,结果居然跑起来了:

#include<bits/stdc++.h>
using namespace std;
double sjc(int a)
{
    double mult = 1;
    for (int i = 1; i <= a; i++)
    {
        mult *= i;
    }
    return mult;
}
int main()
{
    int n;
    cin >> n;
    double sum = 1;
    for (int i = 1; i <= n; i++)
    {
        sum += 1.0 / sjc(i);
    }
    printf("%.8lf", sum);
    return 0;
}

这也让我产生了些好奇心,明明都是完全相同的数据,只因为数据类型的不同,就产生了这样的结果。

通过各种类型的切换,发现:

如果mult为double型,那么即使return时转换为long long,也会正常进行除运算

如果mult为longlong,那么即使return或者运算中强制转化为double,也会将sum直接变成inf而不进行任何有效运算

这与一些文章中说的c/c++中inf的运算并不一致,但具体原因我确实是不得而知了,希望有大佬可以解答一下。但是对我们来说的话,重要的经验就是在数据会变成inf的场景下避免使用long long

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值