老题新解|计算分数加减表达式的值

《信息学奥赛一本通》第69题:计算分数加减表达式的值

题目描述
S n = 1 1 − 1 2 + 1 3 − 1 4 + 1 5 − 1 6 + . . . + ( − 1 ) n − 1 × 1 n S_n=\frac{1}{1}-\frac{1}{2}+\frac{1}{3}-\frac{1}{4}+\frac{1}{5}-\frac{1}{6}+...+(-1)^{n-1}\times\frac{1}{n} Sn=1121+3141+5161+...+(1)n1×n1
输入一个整数 n n n,求 S n S_n Sn
输入格式
输入为一行,含一个正整数 n n n
输出格式
输出为一行,为 S n S_n Sn 的值,结果保留小数点后 4 4 4 位小数。
输入输出样例 #1
输入 #1
2
输出 #1
0.5000
说明/提示
1 ≤ n ≤ 1000 1\leq n\leq 1000 1n1000

大家好,我是莫小特。
这篇文章给大家带来《信息学奥赛一本通》中的第 69 题:计算分数加减表达式的值。

image.png

一、题目描述

洛谷的题号是:B2070 计算分数加减表达式的值

image.png

二、题意分析

这道题是信息学奥赛一本通练习题的第 69 题。

根据输入格式的描述,输入为一个正整数,数据范围: 1 ≤ n ≤ 1000 1\leq n\leq 1000 1n1000,所以使用 int 类型。

int n;
cin>>n;

输入完成后,我们来分析题意,题目要求我们按照公式完成求和计算,我们发现分母是从 1 遍历到 n,因此可以使用 for 循环来完成。

for(int i=1;i<=n;i++)
{

}

研究题目发现,当分母为奇数时用的加法,分母为偶数时用的是减法,所以可以和循环结合在一起。
定义一个新变量存储这个和,求和的初始值一定要赋值为 0。

int sum=0;
for(int i=1;i<=n;i++)
{
	if(i%2==0)//偶数
	{
		sum-=1/i;//偶数做减法
	}
	else//奇数
	{
		sum+=1/i;//奇数做加法
	}
}

最后输出 sum 即可,注意输出时要保留小数点后 4 位,需要使用 printf("%.4lf")

printf("%.4lf",sum);

按照样例输入对数据进行验证。

image.png

我们发现结果为 0,原因在于 sum 是 int 类型,和 printf 的 lf 有冲突,所以需要修改 sum 的类型,并且我们计算的是分数,最后的结果是小数,因此需要将 sum 的类型进行修改。同时计算时,也需要用 1.0 除以 i 这样能确保结果为小数,也可以将 i 强制转换为 double。

double sum=0.0;
for(int i=1;i<=n;i++)
{
	if(i%2==0)//偶数
	{
		sum-=1.0/(double)i;//偶数做减法
	}
	else//奇数
	{
		sum+=1.0/(double)i;//奇数做加法
	}
}

再次验证。

image.png

符合样例输出,到网站提交测评。

image.png

测试通过!

如果对 pow() 比较熟悉,也可以使用这个函数来完成,使用前需要加上 #include<camth> 头文件或者万能头文件,直接根据公式: ( − 1 ) n − 1 × 1 n (-1)^{n-1}\times\frac{1}{n} (1)n1×n1,也就是 pow(-1,i)

sum+=pow(-1,i)*(1.0/(i+1));

这样也可以完成。

三、完整代码

该题的完整代码如下:

代码1:

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n;
	cin>>n;
	double sum=0.0;
	for(int i=1;i<=n;i++)
	{
		if(i%2==0)//偶数
		{
			sum-=1.0/(double)i;//偶数做减法
		}
		else//奇数
		{
			sum+=1.0/(double)i;//奇数做加法
		}
	}
	printf("%.4lf",sum);
    return 0;
}

代码2:

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

四、总结

本题考察了

1、循环求和:利用 for 循环依次累加/累减分数项。

2、奇偶性判断与分支处理:根据分母奇偶决定加法或减法。

3、浮点运算与输出格式:确保分数运算不发生整型截断,结果按要求保留小数位输出。

有以下几点需要注意:

1、浮点精度与类型选择

累加分数和时必须用 double(或 long double)存储,否则会因整型除法导致结果错误。

2、整型除法陷阱

表达式 1/i 若 i 为 int,会先做整除运算变成 0,应改为 1.0/i(double)1/i

3、输出格式控制

使用 printf("%.4lf", sum);cout << fixed << setprecision(4) << sum; 保留 4 位小数。

常见易错点:

(1)初学者容易直接用 int sum 即 sum 没有赋初始值导致计算全为 0(除第一个数外)。

(2)奇偶判断用错(如从 0 开始循环但仍用 %2==0 判偶,逻辑会反)。

(3)pow(-1, i) 使用不当,i 的起始值与公式符号不匹配。

---end---

如果你觉得这篇文章对你有帮助,欢迎点赞、收藏、关注我哦!
如果有更好的方法也可以在评论区评论哦,我都会看哒~

我们下集见~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员莫小特

谢谢你~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值