题目
给定两个数,要求按照题目的要求保留位数并进行科学计数法的表达,然后判断二者是否相同
错误的思路
- 直接将数字进行处理,分成大于1和小于1的不同情况。
- 对于大于1的数字,我们知道,小数点前的位数吗,就是他们在科学计数法中的指数部分
- 对于小于1的数字,我们知道,小数点往后数,到第一个非0数字的长度,就是指数
- 我的代码中对于大于1的数字,进行了小数点前的长度计算,然后根据题目要求的输出长度,去除10来得到最后的位数或者乘10,然后对比输出
- 对于小于1的数字,直接乘10,直到他们大于一个10的倍数,比如题目给n = 3,就不断乘10直到他们大于1000,记录乘10的次数,然后再将这个数除10,然后将乘10的次数减去n + 1,因为本身次数是为了让他们成为0.xxx,结果为xxxx.xxxx,多乘了 n + 1次,然后对比指数部分和数字部分
- 但是这样只能处理两个数都是一样大的位数,对于那种位数不对齐或者大于1小于1掺杂的情况无法得到正确答案,,但如果全考虑的话整个代码就是一堆if else会变得很恶心。。
- 这种方法可以得到19分,但思路很直白
#include<cstdio>
#include<math.h>
struct num {
int number;
int index;
};
num A, B;
double a, b;
int get_num_lenth(float x) {
int key = int(x);
int flag = 0;
while (key != 0) {
flag++;
key /= 10;
}
return flag;
}
int main() {
int n;
scanf("%d", &n);
scanf("%lf", &a);
scanf("%lf", &b);
if (a == 0.0) {
printf("YES 0.");
for (int i = 0; i < n; i++) {
printf("0");
}
printf("*10^0");
}
if (a >= 1 && b >= 1) {
int alen, blen;
alen = get_num_lenth(a);
blen = get_num_lenth(b);
int ansa = alen - n;
int ansb = blen - n;
int flag = (ansa == ansb);
//下面整段逻辑就是为了去获得需要的长度
if (ansa >= 0 && ansb >=0) {
while (ansa != 0) {
a /= 10;
ansa--;
}
while (ansb != 0) {
b /= 10;
ansb--;
}
}
else {
while (ansa != 0) {
a *= 10;
ansa++;
}
while (ansb != 0) {
b *= 10;
ansb++;
}
}
if ((int)a == (int)b && flag) {
printf("YES ");
printf("0.%d*10^%d", (int)a, alen);
}
else {
printf("NO ");
printf("0.%d*10^%d ", (int)a, alen);
printf("0.%d*10^%d", (int)b, blen);
}
return 0;
}
else {
int ans = 0;
while (a < pow(10, n) && b < pow(10, n)) {
a *= 10;
b *= 10;
ans++;
}
ans -= n + 1;
a = (int)a / 10;
b = (int)b / 10;
if ((int)a == (int)b) {
printf("YES ");
printf("0.%d*10^%d", (int)a, -ans);
}
else {
printf("NO ");
printf("0.%d*10^%d ", (int)a, -ans);
printf("0.%d*10^%d", (int)b, -ans);
}
return 0;
}
}
正确的AC思路
- 因为不知道是什么情况,就当字符串处理,之前很多题目也用到了这样的想法,不知道他是什么情况就用字符串读入
- 用字符串读入的话第一个需要注意的点是前导0的问题,比如输入一个0100.0,当做数字读入的时候会自动处理为100.0,而字符串会整个读入,所以第一步就是需要去掉所有的前导0
- 第二个就是如何判断这个数字是大于1的数字还是小于1的数字,这里就不能直接比较了,但我们可以借助于小数点的位置
- 最后为了统一算法,我们将所有的都处理为无小数点的字符串,然后去得到所需要的位数,不够的填0
- 由于最后的处理是得到最终的字符串,所以需要我们在之前的对于小数点的处理的同时得到指数部分
- 具体coding思路在代码中写了注释
#include<string>
#include<cstdio>
#include<iostream>
using namespace std;
int n;
string deal(string str, int& e) {
//删除前导零
int index = 0;
while (str.length() > 0 && str[0] == '0') {
str.erase(str.begin());
}
if (str[0] == '.') {
//小于1先变成最终的无前导0的字符串,同时记录指数
str.erase(str.begin());
while (str.length() > 0 && str[0] == '0') {
str.erase(str.begin());
e--;
}
}
else {
//大于1的找小数点,这个过程和记录指数同步进行
while (index < str.length() && str[index] != '.') {
index++;
e++;
}
}
//有小数点就删除,统一格式
if (str[index] == '.') str.erase(str.begin() + index);
//不加下面这一句话对于0000会出错的
if (str.length() == 0) e = 0;
//找最终的输出
int num = 0;
int k = 0;
string res;
while (num < n) {
if (k < str.length()) {
res += str[k++];
}
else
res += '0';
num++;
}
return res;
}
int main() {
cin >> n;
string stra, strb;
cin >> stra;
cin >> strb;
string a, b;
int ea = 0, eb = 0;
a = deal(stra, ea);
b = deal(strb, eb);
if (a == b && ea == eb) {
cout << "YES 0." << a << "*10^" << ea << endl;
}
else {
cout << "NO 0." << a << "*10^" << ea << " 0." << b << "*10^" << eb << endl;
}
}