PAT 1060

题目

给定两个数,要求按照题目的要求保留位数并进行科学计数法的表达,然后判断二者是否相同

错误的思路

  1. 直接将数字进行处理,分成大于1和小于1的不同情况。
  2. 对于大于1的数字,我们知道,小数点前的位数吗,就是他们在科学计数法中的指数部分
  3. 对于小于1的数字,我们知道,小数点往后数,到第一个非0数字的长度,就是指数
  4. 我的代码中对于大于1的数字,进行了小数点前的长度计算,然后根据题目要求的输出长度,去除10来得到最后的位数或者乘10,然后对比输出
  5. 对于小于1的数字,直接乘10,直到他们大于一个10的倍数,比如题目给n = 3,就不断乘10直到他们大于1000,记录乘10的次数,然后再将这个数除10,然后将乘10的次数减去n + 1,因为本身次数是为了让他们成为0.xxx,结果为xxxx.xxxx,多乘了 n + 1次,然后对比指数部分和数字部分
  6. 但是这样只能处理两个数都是一样大的位数,对于那种位数不对齐或者大于1小于1掺杂的情况无法得到正确答案,,但如果全考虑的话整个代码就是一堆if else会变得很恶心。。
  7. 这种方法可以得到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思路

  1. 因为不知道是什么情况,就当字符串处理,之前很多题目也用到了这样的想法,不知道他是什么情况就用字符串读入
  2. 用字符串读入的话第一个需要注意的点是前导0的问题,比如输入一个0100.0,当做数字读入的时候会自动处理为100.0,而字符串会整个读入,所以第一步就是需要去掉所有的前导0
  3. 第二个就是如何判断这个数字是大于1的数字还是小于1的数字,这里就不能直接比较了,但我们可以借助于小数点的位置
  4. 最后为了统一算法,我们将所有的都处理为无小数点的字符串,然后去得到所需要的位数,不够的填0
  5. 由于最后的处理是得到最终的字符串,所以需要我们在之前的对于小数点的处理的同时得到指数部分
  6. 具体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;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值