PAT A1060 科学记数法经典例题(全string库解决)

46次阅读

共计 1519 个字符,预计需要花费 4 分钟才能阅读完成。

挺操蛋的一道题,我他妈的都服了。。。出这道题我怕是毙了
首先题目里就有几个坑:1. 可能有前导零,比如说 000.00012. 可能有零,比如说 000.0000000
哎,思路感觉最重要,对于字符串处理一定要有思路,知道先干嘛,后干嘛;
首先就要去除前导零,把他变成一个纯净的浮点数;
去除前导零,我们就可以进行分类讨论,因为必定会出现两种情况:1. 第一位是小数点,此时该数为小数;2. 第一位是数字,此时该数为大于零的数;
对于第一种情况,我们应该注意 e 和位数的关系;例如.0002, 其 e 一定是符号位到第一位不为零的数字的距离,也就是 0.2*10^-3。所以对于第一种情况,只需要寻找第一位不为零的数字,过一位 e –,从而使得得到纯净小数的时候,也能得到指数;
注意:两种情况都是不含小数点的数,“0.”后面输出的时候再加
对于第二种情况,我们应该先寻找小数点;这里 e 的记录方式和第一种情况类似,每过一位,e++; 比如 44.2,我们应该是 0.442*10^2,而此时 e 过了两位;当我们找到小数点之后,就应该删除小数点,使我们得到纯净的连续数字;
对于以上两种情况,我们都得到了纯净的连续数字,也就是非小数,不包含小数点的数字,接下来就是对保留位数进行判断;
对于一种情况,就是通过以上步骤,00.00,最后得到的序列为空,此时 e =0,作为零的特殊情况;
后续就是对精度计算,并且对不足位进行补 0 操作;
例如现在得到了 12,我们要求精度位 4 位,所以先建立一个空字符串 s,遍历的同时对精度位进行计算,当 s =”12″ 时,还差两个精度位,所以补两个 0,输出 s =”1200″
最后进行比较的时候就是对指数和保留部分比较,后续输出的时候再 s 前加上“0.”输出就行;
代码如下所示:
#include<iostream>
#include<stdlib.h>
#include<stdio.h>
#include<vector>
#include<string>
using namespace std;
using std::vector;
int n;
string deal(string s,int& e){
int k=0;
while(s.length()>0&&s[0]==’0′){
s.erase(s.begin());
// 去除前导零;
}
if(s[0]==’.’){
// 小于零的数字
s.erase(s.begin());
while(s.length()>0&&s[0]==’0′){
s.erase(s.begin());
// 找到首位非零元素
e–;
}
}else{
while(k<s.length()&&s[k]!=’.’){
k++;
// 寻找小数点
e++;
}
if(k<s.length()){
// 说明有小数点,进行删除
s.erase(s.begin()+k);
}
}
if(s.length()==0){
e=0;// 取出前导零为 0 说明实际为 0
}
int num=0;
k=0;
string res;
while(num<n){
if(k<s.length())
// 如果有数字存在
res+=s[k++];
else
res+=’0′;
num++;
}
return res;
}
int main(){
string s1,s2,s3,s4;
cin>>n>>s1>>s2;
int e1=0,e2=0;
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;
}
system(“pause”);
return 0;
}

正文完
 0