题目描述
题目给出科学计数法的格式的数字A,要求输出普通数字表示法的A,并保证所有有效位都被保留,包括末尾的0。
实现
码前思考
- 这道题目我用了很长的时间,这里主要还是分情况解析问题为主,将情形拆分为exp是大于0,小于0,还是等于0;
代码实现
#include <cstdio>
#include <iostream>
#include <string>
using namespace std;
string input;
string numSign;
string exSign;
string num;
string exStr;
int ex;
int main(){
cin>>input;
numSign = input[0];
input = input.substr(1);
//获取数字部分
int len = 0;
while(input[len]!='E'){
len++;
}
//得到数字部分
num = input.substr(0,len);
//获取指数的符号
exSign = input[len+1];
//然后获取指数大小
exStr = input.substr(len+2);
ex = stoi(exStr);
//cout<<num<<" "<<ex<<exSign;
//接下来针对指数正数和偶数进行调整小数点
if(numSign == "-"){
cout<<"-";
}else{
if(ex == 0){
cout<<num;
}else if(exSign == "-"){
//不为0的指数
printf("0.");
ex--;
for(int i=0;i<ex;i++){
printf("0");
}
//输出数字
for(int i=0;i<num.size();i++){
if(num[i]!='.'){
printf("%c",num[i]);
}
}
}else if(exSign == "+"){
//不为0的指数
//不需要考虑前导0的删除?
//根据小数点进行移动
//超过位数就不用输出小数点
if(ex>=num.size()-2){
//首先是原始输出
for(int i=0;i<num.size();i++){
if(num[i]!='.'){
printf("%c",num[i]);
}
}
ex = ex-num.size();
for(int i=0;i<ex;i++){
printf("0");
}
}else{
//调整小数点,至少有一位
int i=0;
for(;i<ex+1;i++){
if(num[i]!='.'){
printf("%c",num[i]);
}
}
printf(".");
for(;i<num.size();i++){
printf("%c",num[i]);
}
}
}
}
return 0;
}
码后反思
-
我的代码还是会非常复杂,主要体现在没有考虑到小数点的问题!应该不保存小数点的!
-
柳神的思路:
分析:n保存E后面的字符串所对应的数字,t保存E前面的字符串,不包括符号位。当n<0时表示向前移动,那么先输出0. 然后输出abs(n)-1个0,然后继续输出t中的所有数字;当n>0时候表示向后移动,那么先输出第一个字符,然后将t中尽可能输出n个字符,如果t已经输出到最后一个字符(j == t.length())那么就在后面补n-cnt个0,否则就补充一个小数点。 然后继续输出t剩余的没有输出的字符~思路非常简介且清晰
代码如下:
#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; }
二刷代码
此次二刷,我已经会很多string
的骚操作了,所以思路跟柳神的差不多了,也是分块进行求解:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main(){
string input,output;
cin>>input;
//提取符号
char signN = input[0];
input = input.substr(1);
//提取E之前
int posE;
string beforeE;
while(true){
if(input[posE] == 'E'){
beforeE = input.substr(0,posE);
input.erase(0,posE+1);
break;
}else{
posE++;
}
}
//得到指数
char signE = input[0];
input = input.substr(1);
int e = stoi(input);
//接下来移动小数点
if(signE == '-'){
//负的话,如果指数大于1就要移动了
if(e > 1){
beforeE.erase(1,1);//先去处小数点
for(int i=1;i<e;i++){
beforeE = "0"+beforeE;
}
//再补一个
beforeE = "0."+beforeE;
}
}else if(signE == '+'){
//正的话
beforeE.erase(1,1);
int size = beforeE.size();
if(1+e >= size){
//此时没有小数点的
for(int i=0;i<1+e-size;i++){
beforeE += "0";
}
}else{
//有小数点,需要移动小数点位置
beforeE.insert(1+e,".");
}
}
if(signN == '-'){
printf("-");
}
cout<<beforeE;
return 0;
}
nice~不经意间就养成了分块的习惯。