*PAT_甲级_1073 Scientific Notation (20point(s)) (C++)【字符串处理/科学计数法】
程序员文章站
2022-07-15 10:30:11
...
目录
1,题目描述
Sample Input 1:
+1.23400E-03
Sample Output 1:
0.00123400
Sample Input 2:
-1.2E+10
Sample Output 2:
-12000000000
题目描述
就是将科学计数法转为普通的数的表示
2,思路
这种题目处理的方式感觉不固定(可能是刷的还不够)
我的算法
- 用bool型变量signOfNum,signOfExp存放数字部分和指数部分的符号,字符串s存放数字部分,int型exp存放指数;
- 根据signOfNum判断是否输出负号;
- 若指数部分小于0(不包括等于),则先输出0. ,再根据exp判断需要输出多少个0,接着输出数字部分s;
- 若指数部分大于等于0,根据是否输出小数点分成两种情况。指数exp足够大,不需要输出小数点,并根据exp大小输出一定数目的0;否则定位小数点的位置,输出一部分数字,输出小数点,输出数字的剩余部分;
3,AC代码
我的代码
#include<bits/stdc++.h>
using namespace std;
bool cmp1(int a, int b){return a > b;}
int main(){
#ifdef ONLINE_JUDGE
#else
freopen("1.txt", "r", stdin);
#endif // ONLINE_JUDGE
bool signOfNum = false, signOfExp = false;
string s;
char c;
scanf("%c", &c); //读取数字符号
if(c == '+') signOfNum = true;
scanf("%c", &c); //读取小数点前数字
s += c; //将所有数字部分拼接起来
scanf("%c", &c); //读取小数点
scanf("%c", &c); //读取数字部分
while(isdigit(c)){
s += c;
scanf("%c", &c);
}
scanf("%c", &c); //读取指数符号
if(c == '+') signOfExp = true;
int exp;
scanf("%d", &exp); //读取指数部分
if(signOfNum == false) printf("-"); //数字部分为负值 则先输出负号
if(signOfExp == false && exp > 0){ //指数为负
//if(signOfExp == false){
printf("0."); //指数exp超过0时 需要输出0. 并且根据exp在前面补充0
for(int i = 0; i < exp - 1; i++) printf("0");
cout<<s; //首部0补充足后 输出数字部分
}else{ //指数>=0
//while(s[s.size()-1] == '0') s.erase(s.size()-1, 1);//不需要将数字部分尾部的0删去
if(exp >= s.size() - 1){ //不需要小数点
cout<<s;
exp -= (s.size() - 1);
while(exp > 0){ //在尾部补充足够的0
printf("0");
exp--;
}
}else{
int index;
for(index = 0; index <= exp; index++) cout<<s[index];
cout<<'.'; //数字部分中间正确位置插入小数点
for(;index < s.size(); index++) cout<<s[index];
}
}
return 0;
}
柳神解法
把柳神的做法也贴出来学习学习!
#include <iostream>
using namespace std;
int main() {
string s;
cin >> s;
int i = 0;
while (s[i] != 'E') i++;
string t = s.substr(1, i-1);
int n = stoi(s.substr(i+1));
if (s[0] == '-') cout << "-";
if (n < 0) {
cout << "0.";
for (int j = 0; j < abs(n) - 1; j++) cout << '0';
for (int j = 0; j < t.length(); j++)
if (t[j] != '.') cout << t[j];
} else {
cout << t[0];
int cnt, j;
for (j = 2, cnt = 0; j < t.length() && cnt < n; j++, cnt++) cout <<t[j];
if (j == t.length()) {
for (int k = 0; k < n - cnt; k++) cout << '0';
} else {
cout << '.';
for (int k = j; k < t.length(); k++) cout << t[k];
}
}
return 0;
}
4,解题过程
第一搏
果然还是讨厌这种题目。
#include<bits/stdc++.h>
using namespace std;
bool cmp1(int a, int b){return a > b;}
int main(){
#ifdef ONLINE_JUDGE
#else
freopen("1.txt", "r", stdin);
#endif // ONLINE_JUDGE
bool signOfNum, signOfExp;
string s;
char c;
scanf("%c", &c);//读取数字符号
if(c == '+') signOfNum = true;
//else signOfNum = false;
scanf("%c", &c);//读取小数点前数字
s += c;
scanf("%c", &c);//读取小数点
scanf("%c", &c);
while(isdigit(c)){
s += c;
scanf("%c", &c);
}
scanf("%c", &c);//读取指数符号
if(c == '+') signOfExp = true;
int exp;
scanf("%d", &exp);
if(signOfNum == false) printf("-");
if(signOfExp == false){
printf("0.");
for(int i = 0; i < exp - 1; i++) printf("0");
cout<<s;
}else{
//while(s[s.size()-1] == '0') s.erase(s.size()-1, 1);
if(exp >= s.size() - 1){//不需要小数点
cout<<s;
exp -= (s.size() - 1);
while(exp > 0){
printf("0");
exp--;
}
}else{
int index;
for(index = 0; index <= exp; index++) cout<<s[index];
cout<<'.';
for(;index < s.size(); index++) cout<<s[index];
}
}
return 0;
}
第二搏
冷静分析之后,可能是这个问题,后面的0没有去掉。
问题解决了,然而仍然只有5分。
在牛客网上运行完全没问题(不同的编译器可能会有问题)
第三搏
突然想到,如果E后面为0会怎么样
于是测试了下面的数据
+1.23400E-0
发现问题了!当为E-0时,原先代码设定的逻辑是:遇到E后为负,直接先输出 0.,所以改进一下条件(我的算法是,将符号与数字分离,所以exp总数大于等于0)多加了红色框部分的内容(一开始的代码如注释所示)
第四搏
冷静分析后,想到前面第二搏修改的部分(若输入为+1.23400E+03,则输出改为1234,而不是1234.00) 会不会是多余的
于是我试着把这部分注释掉,再次运行
飒!