PAT-ADVANCED1060——Are They Equal

解析PAT-ADVANCED 1060题目,讲解如何在给定有效位数的情况下,判断两个浮点数是否相等。通过科学计数法转换与比较,提供C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我的PAT-ADVANCED代码仓:https://github.com/617076674/PAT-ADVANCED

原题链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805413520719872

题目描述:

题目翻译:

1060 它们是否相等

如果机器只能保存3位有效数字,则浮点数12300和12358.9被认为是相等的,因为它们都保存为0.123×10 ^ 5。现在给出一台机器上的有效位数和两个浮点数,你需要指出它们在该机器中是否被视为相等。

输入格式:

每个输入文件包含一个测试用例,它给出三个数字N,A和B,其中N(<100)是有效位数,A和B是要比较的两个浮点数。 每个浮点数都是非负数,不大于10 ^ 100,即总位数小于100。

输出格式:

对于每个测试用例,如果两个数字处理相等,则在一行中打印“Yes”,然后以标准形式编号为0.d [1] ... d [N] * 10 ^ k(d [1]> 0 除非数字是0);如果相等,则输出“NO”,然后是标准形式的两个数字。 所有数字由一个空格分隔,一行末尾没有多余空格。

注意:不考虑四舍五入。

输入样例1:

3 12300 12358.9

输出样例1:

YES 0.123*10^5

输入样例2:

3 120 128

输出样例2:

NO 0.120*10^3 0.128*10^3

知识点:字符串

思路:按整数部分是否为0来分情况讨论

先写几个坑点:

(1)题目的数字可能有前导0,即00123这种形式。

(2)题目中的数字可能出现0.000、1.000这种形式。

(3)即使指数是0,也要写出来。

(4)指数可以是负数,也就是说对于0.000012的情况,其结果不应该是0.000,而应该是0.120 * 10 ^ -4次。

题目的要求是将两个数改写为科学计数法的形式,然后判断它们是否相等。而科学计数法的写法一定是如下格式:0.a1a2a3... * 10 ^ e,因此只需要获取到科学计数法的本体部分a1a2a3指数e,即可判定两个数在科学计数法形式下是否相等。

按整数部分是否为0来分情况讨论,即

(1)0.a1a2a3...

(2)b1b2...bm.a1a2a3...

现在来考虑这两种情况的本体部分与指数分别是什么(以下讨论均按有效位数为3进行)。对(1)来说,由于在小数点后面还可能跟着若干个0,因此本体部分是从小数点后第一个非零位开始的3位(即akak + 1ak + 2,其中ak是小数点后第一个非零位),而指数则是小数点与该非零位之间0的个数的相反数(例如0.001的指数为-2)。在分析清楚后,具体的代码实现逻辑也就成形了,即令指数e的初值为0,然后在小数点后每出现一个0,就让e减1,直到到达最后一位(因为有可能是小数点后全为0的情况)或是出现非零位为止。

然后来看(2)的情况,假设b1不为零。很显然,其本体部分就是从b1开始的3位,而指数则是小数点前的总位数m。具体实现中,则可以令指数e的初值为0,然后从前往后枚举,只要不到达最后一位(因为有可能没有小数点)或是出现小数点,就让e加1。

如何区分给定的数是(1)还是(2)呢?先去除所有的前导0,按去除前导0后的字符串的第一位是否是小数点来判断其属于(1)或是(2)。

由于需要让两个数的科学计数法进行比较,因此必须将各自的本体部分单独提取出来。比较合适的方法是,在按上面的步骤处理(1)时,将前导0、小数点、第一个非零位前的0全部删除,只保留第一个非零位开始的部分(即akak + 1ak + 2...)。在处理(2)时,将前导0、小数点删除,保留从b1开始的部分(即b1b2...bma1a2a3...)。这些删除操作可以在上面获取指数e的过程中同时做到(使用string的erase函数)。之后便可以对剩余的部分取其有效位数的部分赋值到新字符串中,长度不够有效位数则在后面补0。

最后只要比较本体部分和指数是否都相等,就可以决定输出“YES”或“NO”。

时间复杂度和空间复杂度的分析对本题来说意义不大。

C++代码:

#include<iostream>
#include<string>

using namespace std;

int n;	//有效位数

string deal(string s, int &e);

int main(){
	string s1, s2, s3, s4;
	cin >> n >> s1 >> s2;
	int e1 = 0, e2 = 0;	//e1,e2为s1与s2的指数
	s3 = deal(s1, e1);
	s4 = deal(s2, e2);
	if(s3 == s4 && e1 == e2){
		cout << "YES 0." << s3 << "*10^" << e1 << endl;
	}else{
		cout << "NO 0." << s3 << "*10^" << e1 << " 0." << s4 << "*10^" << e2 << endl;
	}
}

string deal(string s, int &e) {
	int k = 0;	//s的下标
	while(s.length() > 0 && s[0] == '0') {
		s.erase(s.begin());	//去掉s的前导零
	}
	if(s[0] == '.') {	//去掉前导零后是小数点,说明s是小于1的小数
		s.erase(s.begin());	//去掉小数点
		while(s.length() > 0 && s[0] == '0') {
			s.erase(s.begin());	//去掉小数点后非零位前的所有零
			e--; //每去掉一个0,指数e减1
		}
	} else {	//去掉前导零后不是小数点,则找到后面的小数点删除
		while(k < s.length() && s[k] != '.') {	//寻找小数点
			k++;
			e++;	//只要不碰到小数点就让指数e++
		}
		if(k < s.length()) {
			s.erase(s.begin() + k);	//把小数点删除
		}
	}
	if(s.length() == 0) {	//如果去除前导零后s的长度变为0,说明这个数是0
		e = 0;
	}
	int num = 0;
	k = 0;
	string res;
	while(num < n){	//只要精度还没有到n 
		if(k < s.length()){
			res += s[k++];
		}else{
			res += '0';
		}
		num++;
	}
	return res;
}

C++解题报告:

 

内容概要:本文详细探讨了基于MATLAB/SIMULINK的多载波无线通信系统仿真及性能分析,重点研究了以OFDM为代表的多载波技术。文章首先介绍了OFDM的基本原理和系统组成,随后通过仿真平台分析了不同调制方式的抗干扰性能、信道估计算法对系统性能的影响以及同步技术的实现与分析。文中提供了详细的MATLAB代码实现,涵盖OFDM系统的基本仿真、信道估计算法比较、同步算法实现和不同调制方式的性能比较。此外,还讨论了信道特征、OFDM关键技术、信道估计、同步技术和系统级仿真架构,并提出了未来的改进方向,如深度学习增强、混合波形设计和硬件加速方案。; 适合人群:具备无线通信基础知识,尤其是对OFDM技术有一定了解的研究人员和技术人员;从事无线通信系统设计与开发的工程师;高校通信工程专业的高年级本科生和研究生。; 使用场景及目标:①理解OFDM系统的工作原理及其在多径信道环境下的性能表现;②掌握MATLAB/SIMULINK在无线通信系统仿真中的应用;③评估不同调制方式、信道估计算法和同步算法的优劣;④为实际OFDM系统的设计和优化提供理论依据和技术支持。; 其他说明:本文不仅提供了详细的理论分析,还附带了大量的MATLAB代码示例,便于读者动手实践。建议读者在学习过程中结合代码进行调试和实验,以加深对OFDM技术的理解。此外,文中还涉及了一些最新的研究方向和技术趋势,如AI增强和毫米波通信,为读者提供了更广阔的视野。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值