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×105 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 10100, 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.youkuaiyun.com/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;
}