题目描述:给出两个数,将它们保留N位小数的科学计数法后是否相等。如果相等,则输出YES,并给出转换结果;如果不相等输出NO,并给出两个数的转换结果。
样例:
输入
3 12300 12358.9
输出
YES 0.123*10^5
输入
3 120 128
输出
NO 0.120*10^3 0.128*10^3
思路:
科学计数法的格式一定为:0.abc...*10^e
,所以需要获取到本体部分abc...
与指数e
,即可以判断两数科学计数法是否相等。考虑到数据本身,可能为:①小于1(0.abcde....
)或者②大于1(xy..z.abcd
)的小数,分别讨论这两种情况。
①由于小数点后可能存在若干个0,所以本体部分为小数点后第一个非零位开始的N位,指数则是小数点与该非零位之间0的个数的相反数(如0.001
指数为-2
)。
因此令e的初值为0,小数点后每出现一个0,就让e
减一,直到到达最后一位或者出现非零位为止。
②本体部分为x
开始的N位,指数为小数点前的数位的总位数m
。因此令指数e
的初值为0,然后从前往后枚举,直到出现小数点或者没有达到最后一位(因为可能没有小数点),就让e
加1。
完整代码如下:
#include <cstring>
#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的前导0
s.erase(s.begin());
}
if (s[0] == '.') { //去除前导0后第一位为小数点,说明s是小于1的小数
s.erase(s.begin()); //去除小数点
while (s.length() > 0 && s[0] == '0') {
s.erase(s.begin()); //去除小数点后非零位前的所有0
e--;
}
} else {
//去除前导0后不是小数点,说明是大于1的小数,找到小数点删除
while (k < s.length() && s[k] != '.') { //寻找小数点位置
k++;
e++;
}
if (k < s.length()) {
s.erase(s.begin() + k); //删除小数点
}
}
if (s.length() == 0) { //该数为0
e = 0;
}
int num = 0;
k = 0;
string res;
while (num < n) { //精度还没有达到n
if (k < s.length()) { //只要还有数字,就加到res末尾
res += s[k++];
} else { //没有就添0
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;
}
}