1060 Are They Equal (25 point(s))

1060 Are They Equal (25 point(s))

If a machine can save only 3 significant digits, the float numbers 12300 and 12358.9 are considered equal since they are both saved as 0.123×10​5​​ with simple chopping. Now given the number of significant digits on a machine and two float numbers, you are supposed to tell if they are treated equal in that machine.

Input Specification:

Each input file contains one test case which gives three numbers N, A and B, where N (<100) is the number of significant digits, and A and B are the two float numbers to be compared. Each float number is non-negative, no greater than 10​100​​, and that its total digit number is less than 100.

Output Specification:

For each test case, print in a line YES if the two numbers are treated equal, and then the number in the standard form 0.d[1]...d[N]*10^k (d[1]>0 unless the number is 0); or NO if they are not treated equal, and then the two numbers in their standard form. All the terms must be separated by a space, with no extra space at the end of a line.

Note: Simple chopping is assumed without rounding.

Sample Input 1:

3 12300 12358.9

Sample Output 1:

YES 0.123*10^5

Sample Input 2:

3 120 128

Sample Output 2:

NO 0.120*10^3 0.128*10^3

这题需要考虑的特殊情况太多。如:

1. 整数部分也可能有前导0,如00012和12的比较。

2. 0的特殊判断(我认为此题不太严谨的地方有0的指数怎么写是有争议的,按照题解应该是0)。 

3. 我的思路是首先去掉干扰的0,然后分成整数和小数分别处理,其中小数又分成<1的(0.xxxx)和>=1的(xx.xx)来处理。

此题的感受:

1. PAT的用例可以说是周密了,必须要非常仔细地考虑所有的特殊情况,要想一次性AC不是一件容易的事情。

2. 认真读题,没有完整思路之前不要动手!

3. 熟悉STL会起到事半功倍的效果。看看自己的代码和大神代码的区别!

#include<iostream>
#include<string>
#define max 107
using namespace std;
string to_String(int n)//int转string来自网络 
{
	if(n==0) return "0";
    int m = n;
    char s[max];
    char ss[max];
    int i=0,j=0;
    if (n < 0)// 处理负数
    {
        m = 0 - m;
        j = 1;
        ss[0] = '-';
    }    
    while (m>0)
    {
        s[i++] = m % 10 + '0';
        m /= 10;
    }
    s[i] = '\0';
    i = i - 1;
    while (i >= 0)
    {
        ss[j++] = s[i--];
    }    
    ss[j] = '\0';    
    return ss;
}
bool isZero(string s){
	for(int i=0;i<s.length();i++){
		if(s[i]!='0'&&s[i]!='.') return false;
	}
	return true;
}
string notation(string s,int n){
	if(isZero(s)){
		string ans = ""; 
		for(int i=0;i<n;i++) ans+='0'; 
		ans =  "0."+ans+"*10^0";
		return ans;
	}
	while(s.length()>0&&s[0]=='0'){
		s.erase(s.begin());//去掉s的前导0 
	}
	if(s[0]=='.') s='0'+s;//如果直接就是小数点,为它补0 
	//得到有效位 
	string sig = "";int idx = 0;
	bool start = false;
	for(int i=0;i<s.length()&&idx<n;i++){
		if(s[i]=='.') continue;
		if(!start&&s[i]>'0'&&s[i]<='9') start=true;
		if(start){
			sig += s[i];idx++;
		}
	}
	while(idx<n){
		sig=sig+"0";idx++;
	}
	int exp=0;string ans="";
	if(s.find('.')!=s.npos){//是小数 
		if(s[0]=='0'){//是0.xxx的形式,判断0.以后还有多少个0 
			bool hasPoint = false;
			for(int i=0;i<s.length();i++){
				if(!hasPoint&&s[i]=='.'){
					hasPoint = true;
					continue;
				} 
				if(hasPoint){
					if(s[i]=='0') exp--;
					else break;
				}
			}
		}
		else{//是xx.xx形式,判断整数部分有多少位 
			exp = s.find('.');
		}
	}
	else{//不是小数 
		exp	= s.length(); 
	}
	ans = "0."+sig+"*10^"+to_String(exp);
	return ans;
}
int main(void){
	string s1,s2;int n;cin>>n>>s1>>s2;
	s1 = notation(s1,n);
	s2 = notation(s2,n);
	if(s1==s2){
		cout<<"YES"<<" "<<s1<<endl;
	}
	else{
		cout<<"NO"<<" "<<s1<<" "<<s2<<endl;
	}
	return 0;
}

大神思路:

读入字符串后,把它想成一个数字串。整体思路:得到有效位、求指数。

1. 首先去除前置0(可能是0.xxxx形式或者00xxx形式)。

2. a) 此时如果s[i]是小数点,则说明这是一个小于1的数(0.xxxx形式),然后依次去除小数点后的0,每去除一个指数自减1。

b) 此时如果不是小数点,则说明这个数大于1,找点小数点并删除小数点(可能不存在),每移动一个位置则指数自加1。

3. 此时已经得到了指数。此时的字符串完全是有效位,然后根据有效精度取相应的位数,如果不足需要补零

大神代码(https://blog.csdn.net/weixin_41724000/article/details/79948581):

/*copyright@算法笔记(胡凡,曾磊)*/
/*2018/4/15                     */
 
#include<cstdio>
#include<string>
#include<iostream>
using namespace std;
int n;//有效位数
string deal(string s,int &e){
	int k=0;//s的下标
	while(s.length()>0&&s[0]=='0'){
		s.erase(s.begin());//去掉s的前导0 
	} 
	if(s[0]=='.'){
		s.erase(s.begin());//去掉前导0后是小数点,说明s是小于1的小数
		while(s.length()>0&&s[0]=='0'){
			s.erase(s.begin());//去掉小数点后非零位前的所有零
			e--;//每去掉一个零,指数e减1 
		} 
	} else{//去掉所有前导零后不是小数点,则找到后面的小数点删除 
		while(k<s.length()&&s[k]!='.'){
			k++;
			e++;//只要不碰到小数点就让指数e++ 
		}
		if(k<s.length()){//while结束后k<s.length(),说明碰到了小数点 
			s.erase(s.begin()+k);//把小数点删除 
		}
	}
	if(s.length()==0){
		e=0;//如果去掉前导零后s的长度变为0,说明这个数为0 
	}
	int num=0;
	k=0;
	string res;
	while(num<n){
		if(k<s.length())res+=s[k++];//只要还有数字,就加到res末尾
		else res+='0';//否则res末尾添加0
		num++;//精度加1 
	} 
	return res;
}
 
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;
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值