题目链接
1024 科学计数法
题目描述
科学计数法是科学家用来表示很大或很小的数字的一种方便的方法,其满足正则表达式 [+-][1-9].[0-9]+E[+-][0-9]+,即数字的整数部分只有 1 位,小数部分至少有 1 位,该数字及其指数部分的正负号即使对正数也必定明确给出。
现以科学计数法的格式给出实数 A,请编写程序按普通数字表示法输出 A,并保证所有有效位都被保留。
输入格式:
每个输入包含 1 个测试用例,即一个以科学计数法表示的实数 A。该数字的存储长度不超过 9999 字节,且其指数的绝对值不超过 9999。
输出格式:
对每个测试用例,在一行中按普通数字表示法输出 A,并保证所有有效位都被保留,包括末尾的 0。
输入样例 1:
+1.23400E-03
输出样例 1:
0.00123400
输入样例 2:
-1.2E+10
输出样例 2:
-12000000000
题目大意
给你一个科学计数法形式的数字,转化为正常形式
解题思路
个人感觉非常恶心的一个题,当时也是放了好久才做,属于那种看到题目就不想做的那种
- 遇到的第一个问题是判断这个数字是否大于零,这个比较简单,只需要看最一开始的符号是正是负就可以了
- 然后遇到的问题就是分别求出小数部分和阶数,因为有
E
这个字符的存在,所以我们可以先找到E
,然后1
到i-1
就是小数部分,i+1
到最后
是阶数部分,用substr进行截断,拿题中所给的例子举例
- 还有个问题就是
并保证所有有效位都被保留,包括末尾的 0
和且其指数的绝对值不超过 9999
因为有这两条的出现,就导致想改成double
类型直接进行运算是行不通的,必须用字符串来模拟小数点的移动,这里就回出现两个问题- 小数点左移时,一定会出现
0.
开头的情况 - 小数点右移时,会出现两种情况
- 小数点右移后还存在,这时候末尾的零还需要保留(
1.23400
到123.400
) - 小数点右移后需要补零(
1.23400
到1234000
)
- 小数点右移后还存在,这时候末尾的零还需要保留(
- 小数点左移时,一定会出现
总之需要满分此题还是有一定难度的,每一步在题解中都有比较详细的注释
题解
#include<bits/stdc++.h>
using namespace std;
int main(){
string a;
cin>>a;
if(a[0]=='-') {
cout << "-";
}
int i=0;
while(a[i]!='E') i++;
string s=a.substr(1,i-1); //相当于该数字
string t=a.substr(i+1); //相当于指数部分
//substr的用法为
//string类型变量.substr(开始截断的位置,结束截断的位置)
//上面两行是从起始位置1(包括1)到位置i-1(包括i-1)
//和起始位置i+1(包括i+1)到不填(默认最后位置)
int y=stoi(t);
if(y<0){
//y小于零相当于小数点相左移,因为给定的整数部分只有一位,所以一定是0.开头
cout<<"0.";
for(int j=0;j<abs(y)-1;j++) cout<<"0";
//这里因为已经提前输出了一个0.了所以只需要输出y的绝对值(因为y小于0时才进入这个循环)减1个0,abs是绝对值的意思
for(int j=0;j<s.length();j++){
if(s[j]!='.') cout<<s[j];
// 输出该数字除了小数点以外的所有位数
}
}
else{
//y大于零相当于小数点右移
cout<<s[0];
//因为第一位一定是非零的数字在小数点前,所以先输出第一位
int cnt,j;
for(j=2,cnt=0;j<s.length()&&cnt<y;j++,cnt++) cout<<s[j];
//这里有两种情况,所以在for循环中需要有两个判断条件
//1.在小数点右移后,小数点还存在(比如1.234到123.4)
//2.在小数点右移后,小数点不存在了(1.234到123400)
if(j==s.length()){
//这里代表小数点不存在了还要但是还要右移,这时候需要补零
for(int k=0;k<y-cnt;k++) cout<<"0";
}
else{
//这里代表右移已经结束了,但是小数点还存在
cout<<".";
for(int k=j;k<s.length();k++) cout<<s[k];
}
}
}