题目大意:
给出两个数,写成保留N位小数的科学计数法之后是否相等,相等输出YES给出转换结果,不等输出NO,分别给出转换结果。
思路:
1)题目要求将两个数改写为科学计数法的形式,然后判断他们是否相等。即写成0.a1a2a3…*10^e的形式,所以只需要取到科学计数法的本体a1a2a2及指数e,
即可判定两个数在科学计数法的形式下是否相等。
2)考虑数据本身,分两种情况来看:
- 0.a1a2a3…
由于在小数点后跟着若干个0,因此本体部分为小数点后第一个非0位开始的三位,指数部分时小数点与该非0位之间0的个数的相反数。(0.001的指数为-2)
可以令指数e的初值为0,然后在小数点后每出现一个0.就让e-1,直到达到最后一位(可能会有小数点后全0的情况),或是出现非0位为止。 - b1b2…bm.a1a2a3…
假设b1不为0,显然本体部分就是从b1开始的三位,指数则是小数点前的总位数m。
可以令指数e的初值位0,然后在小数点后每出现一个0,就让e-1,直到达到最后的一位,或是出现非0位为止。
3)该题可能出现前导0的情况,即在上述1或2的数据之前还会有若干个0,如000.01或00123.45,输入数据后的第一步便是去去除前导0。
通过去除前导0后第一位是否是小数点来判断其属于1还是2。
AC代码:
//PAT_A 1060
#include<iostream>
#include<string>
using namespace std;
int n;
string deal(string s, int& e) {
int k = 0;
while (s.length() > 0 && s[0] == '0') {//去除前导0
s.erase(s.begin());
}
if (s[0] == '.') {//s<1 0.a1a2..
s.erase(s.begin());
while (s.length() > 0 && s[0] == '0') {
s.erase(s.begin());
e--;
}
}
else {//s>1 找见后面的小数点删除
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,说明这个数是0
int num = 0;
k = 0;
string res;
while (num < n) {//还没有到达精度。
if (k < s.length()) {
res += s[k];
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;
return 0;
}