《算法笔记》读书记录DAY_18

本文介绍了如何使用C++ STL库中的string类型实现科学计数法转换,通过实例演示了去除前导零、确定指数和浮点数部分的方法,以判断两个数是否相等。

CHAPTER_6  C++STL相关

6.3字符串string

在c语言中,我们使用char数组来存放字符串,有些操作会显得很麻烦。因此,STL中加入了string类型,可以更方便的让我们对字符串进行操作。要使用string,需要添加头文件#include <string>

string的用法记录在《算法笔记》P202-P209。更详细的用法可以参考博客c++中string的用法_我是一片小树叶的博客-优快云博客_c++string用法

我们来看一道题目,以此来熟悉string的用法。

题目:

给出两个数,把他们写成科学计数法(保留N位小数)的形式之后,问他们是否相等。若相等,则输出“YES”,并给出该转换结果;若不等,则输出“NO”,并分别给出两个数的转换结果。

输入样例1:

3 12300 12308.9

输出样例1:

YES 1.230*10^4

输入样例2:

3 120 128

输出样例2:

NO 1.200*10^2 1.280*10^2

思路:

我们使用string来读入两个数,便于对数字进行操作。考虑数据本身,我们读入的数字有两种情况:(1)0.a_{1}a_{2}a_{3}... (2)b_{1}b_{2}...b_{m}.a_{1}a_{2}... 。即按照整数部分是否为0来分类。

首先,我们要解决一个小问题:去掉数字的前导0。例如:输入为000.123或者0012.3。我们先要把前面多余的0给去掉,以便后面的统一处理。而去掉前导0的方法很简单,使用string类的erase()方法即可。

科学计数法将数表示为两部分:浮点数部分10的指数部分。如果浮点数部分和指数部分均相等,那么判断为相等YES。反之为不等NO。对于(1)(2)两种情况,我们分别讨论它们的浮点数和指数部分的界定。为了便于讨论,我们假设保留3位小数,即N=3。

情况(1) 0.a_{1}a_{2}a_{3}... 。首先我们找到小数点之后第一个非0数字 a_{k} 。找到后,我们的指数e也就确定了,e=-k。例如0.0012,第一个非零数字为 a_{3} ,那么指数部分e=-3。e其实也就是中间0的个数加一,再取相反数。找到 a_{k} 后,在其后面加上小数点,再往后数3位即可组成其小数部分,如果后面不足3位,将不足的位数补0。如0.0012补为1.200。

但是,对于情况(1),还有种可能我们没有考虑:如果我们找不到第一个非0数字 a_{k} 呢?例如0.000的小数点后面全为0。这种情况做如下处理:当遍历完数字却找不到 a_{k} 时,我们直接自原小数点后的第四位数字开始全部截去(即保留3位),即可获得其浮点数部分。显然指数部分e=0。

情况(2) b_{1}b_{2}...b_{m}.a_{1}a_{2}... 。去掉前导0之后,第一个数字 b_{1} 一定非0。指数部分为原小数点前的总位数减一,即m-1。浮点数部分为 b_{1} 加上后面三位数,如果位数不足则补0。例如123.4,指数e=3-1=2,浮点数部分为1.234。

对于情况(2),也有一种特殊情况:如果数字没有小数点,我们怎么确定指数e呢?例如123000。很简单,指数为数字总位数减一,同样也是m-1。

综上所述,我们已经能够对两种情况分类处理。因此我们还需要最后一步:确定数字是情况1还是情况2。这显然不难,我们再去除前导0后,如果第一位为小数点则为情况1,反之为情况2。

参考代码:

#include<iostream>
#include<string>

using namespace std;

int n;                                   //保留n位数 

void deal(string s,string &f,int &e) {
	int k,flag=0;
	while(s.size()>1&&s[0]=='0') {       //去掉前导0 
		s.erase(0,1);
	}
	if(s=="0") {         	            //去掉前导后可能出现一种情况,只剩 
		f="0."+string(n,'0');           //一个0,此处单独处理这种情况 
		e=0;
		return;
	}
	if(s[0]=='.') {                     //情况(1) 
		for(k=1;k<s.size();k++) {       //i从1开始,跳过s[0]即小数点 
			if(s[k]!='0') {
				flag=1;
				break;
			}
		}
		if(flag==0) {              //小数点后面全是0 
			f="0."+string(n,'0');
			e=0;
			return;
		}
		else {                          //找到了小数点后第一个非0数 
			e=-k;
			s.insert(k+1,".");          //第一个非0数后插入小数点
			f=s.substr(k,2);
			k=k+2;                      //将第一个非0数和小数点计入f串,k往后移2位 
			while(f.size()<n+2&&k<s.size()) {    //从小数点后面数字开始遍历,将它们加入浮点部分 
				f.insert(f.end(),s[k]);          //将s[i]加入f末尾
				k++;
			}
			if(f.size()<n+2)                     //如果长度不够,用0补至n位小数 
				f=f+string(n+2-f.size(),'0');
			return; 
		}
	}
	if(s[0]!='.') {                     //情况(2) 
		for(k=0;k<s.size();k++) {       //从头遍历串 
			if(s[k]=='.') {
				flag=1;
				break;
			}
		}
		if(flag==1) {                   //找到小数点 
			e=k-1;
			f=s.substr(0,1)+"."; 	             //将第一个数和小数点计入f串
			s.erase(k,1);
			k=1;                                 //将小数点去掉,并将k指向第二个元素 
			while(f.size()<n+2&&k<s.size()) {    //从第二个数字开始遍历,将它们加入浮点部分 
				f.insert(f.end(),s[k]);          //将s[i]加入f末尾
				k++;
			}
			if(f.size()<n+2)                     //如果长度不够,用0补至n位小数 
				f=f+string(n+2-f.size(),'0');
			return; 			 
		}
		else {                          //没有小数点 
			e=s.size()-1;
			f=s.substr(0,1)+"."; 	             //将第一个数和小数点计入f串
			k=1;                                 //将k指向第二个元素 
			while(f.size()<n+2&&k<s.size()) {    //从第二个数字开始遍历,将它们加入浮点部分 
				f.insert(f.end(),s[k]);          //将s[i]加入f末尾
				k++;
			}
			if(f.size()<n+2)                     //如果长度不够,用0补至n位小数 
				f=f+string(n+2-f.size(),'0');
			return; 			
		}
	}
	
}

int main() {
	int e1,e2;                 //e1、e2保存两个数的指数部分 
	string s1,s2,f1,f2;        //f1、f2保存两个数的浮点数部分 
	cin>>n>>s1>>s2;
	deal(s1,f1,e1);
	deal(s2,f2,e2);
	if(f1==f2&&e1==e2)
		cout<<"YES "<<f1<<"*10^"<<e1<<endl;
	else
		cout<<"NO "<<f1<<"*10^"<<e1<<" "<<f2<<"*10^"<<e2<<endl;		
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值