1060 Are They Equal (25 分)(保留浮点数)(string字符串处理)

1060 Are They Equal (25 分)

If a machine can save only 3 significant digits, the float numbers 12300 and 12358.9 are considered equal since they are both saved as 0.123×10​5​​ with simple chopping. Now given the number of significant digits on a machine and two float numbers, you are supposed to tell if they are treated equal in that machine.

Input Specification:

Each input file contains one test case which gives three numbers N, A and B, where N (<100) is the number of significant digits, and A and B are the two float numbers to be compared. Each float number is non-negative, no greater than 10​100​​, and that its total digit number is less than 100.

Output Specification:

For each test case, print in a line YES if the two numbers are treated equal, and then the number in the standard form 0.d[1]...d[N]*10^k (d[1]>0 unless the number is 0); or NO if they are not treated equal, and then the two numbers in their standard form. All the terms must be separated by a space, with no extra space at the end of a line.

Note: Simple chopping is assumed without rounding.

Sample Input 1:

3 12300 12358.9

Sample Output 1:

YES 0.123*10^5

Sample Input 2:

3 120 128

Sample Output 2:

NO 0.120*10^3 0.128*10^3

/**
本题题意就是: 给出一个精确位(eg:3 就是保留3位小数.) 然后给出两个浮点型数字,
               此时需要写出两个浮点型数字经过小数保留后 观察它们的有效位 和科
               学计数法的指数位是否相同

本题问题:
               条件比较多, 没有考虑完全, 代码冗余

               
本题思路:
                两个浮点型小数用string类型表示,(运用stl中的方法对字符串进行处理)

                本题注意点有4个:
                                1. 对于 0.00 与 0 的情况 应该相等 并且科学计数法的指数为 0
                                   通过记录两个字符串0 和 .的个数, 最终判断 0的长度 与字符串的长度是否相等,如果相同就直接将s1 , s2 置 0
                                2. 对于 数字可以能存在前导 0 的情况 eg: 005 , 与 00.5 这种情况就该去除前导0
                                   a.当字符串的整形值 < 1时 截取 0.后的字符串(包括0.)
                                   b.当字符串为整形值 >= 1时 截取非0后的字符串
                                3. 对于 a, b情况要分别处理 a.记录除了0. 以外0的个数就是指数的值
                                                           b. 记录小数点前的所有数值个数就是指数的值(记住在保留值时要去除小数点)
                                4. 当输入浮点类型数字不足保留n位小数时 记得需要添0来补充
                                    判断字符串的长度 与 n的大小, 长度不够 用0来凑。( s += '0';)
                

**/

未化简代码:

                  

#include<iostream>
using namespace std;
int n;
string a, b;
bool isZero = false;
void change(string &s){
	s = s.substr(0, n);
	if(s.size() < n + 1){
		int length = n - s.size();
		while(length--){
			s += '0';
		}
	}
}
int save(string &s){
	int cnt = 0;
	if(s[0] != '0'){ //string类型 != 整形 是不会报错了 
		for(int i = 0; i < s.size(); i++){	
			if(s[i] == '.')
			{
				s.erase(s.begin() + i); //出错点主要是没有考虑到保留小数时 原小数点需要去掉, 才能继续保留余下位置 
				return cnt;
			}
			cnt++;
		}
		return cnt;
	}else{
		for(int i = 2; i < s.size(); i++){
			if(s[i] != '0'){
				s = s.substr(2 + abs(cnt));
				return cnt;
			}
			cnt--;
		}
		if(s.size() > 1)
			s = s.substr(2 + abs(cnt));
		return cnt;
	}
}
void judgeZero(string &s1, string &s2){ //判断是否为0 (需要优化。) 
	int length = max(s1.size(), s2.size()), cnt1 = 0, cnt2 = 0;
	for(int i = 0; i < length; i++){
		if(i < s1.size())
			if(s1[i] == '0' || s1[i] == '.')
				cnt1++;
		if(i < s2.size())
			if(s2[i] == '0' || s2[i] == '.')
				cnt2++;
	}
	if(cnt1 == s1.size())
		s1 = "0";
	if(cnt2 == s2.size())
		s2 = "0";
}
void delPreZero(string &s){ //去除前导0 
	if(s.size() >= 2 && s[0] == '0' && s[1] != '.')
		for(int i = 0; i < s.size(); i++){
			if(s[i] == '.'){
				s = s.substr(i - 1);
				break;
			}else if(s[i] != '0'){
				s = s.substr(i);
				break;
			}
		}
}
int main(){
	int g;
	int k1 = 0, k2 = 0;
	cin >> n >> a >> b;
	judgeZero(a, b);
	delPreZero(a);
	delPreZero(b);
	k1 = save(a);
	k2 = save(b);
	change(a);
	change(b);
	if(k1 == k2 && a == b)
		printf("YES 0.%s*10^%d\n", a.c_str(), k1);
	else
		printf("NO 0.%s*10^%d 0.%s*10^%d\n", a.c_str(), k1, b.c_str(), k2);
	return 0;
} 

化简后的代码:

           思路:

                     /**
本题思路
        化简了代码 逻辑也更加清晰, 具体的步骤是
                                1. 先去除前导0,  
                                2. 判断字符串转换为int型数值 是 >= 1 或是 < 1的情形
                                    a.如果 < 1 表示此时 s[0] 为 '.'因为去除了前导0
                                       判断时 需要知道.之后0的数量, 遇到0 就s.erase[0]
                                       (删除0{要注意删除元素时 , 字符串长度也在改变})元素,
                                        e--(指数减1) 当遇到了非0元素就跳出循环
                                    b. 如果 >= 1, 当遇到 '.'时就跳出循环 并删除 '.'(保留小数时,更方便处理小数
                                    后的数字),没遇到'.'时 e++(指数 +1);
                                3. 此时处理完了字符串 此时的字符串都会是存数字形势:
                                    eg 0.123 会变为 123的形势 , 00123依然是 123, 123也是123的形势
                                    至于需要特殊处理的0元素, 此时在 2步骤 的a条件下已经将0 删除完毕,
                                    当s.size() = 0时 就是0元素, 此时将 指数 赋值 为 0
                                4.最后保留小数, 先截取字符串 s.substr(0,n), 当s的长度小于 < n时
                                  就在字符串后添加0. eg: s += '0';      
**/

 

#include<iostream>
using namespace std;
int n;
void del(string &s, int &e){
	while(s.size() > 0 && s[0] == '0')
		s.erase(s.begin());
	if(s[0] == '.'){ //数值 > 0 时 
		s.erase(s.begin());
		for(int i = 0; i < s.size(); ){ //s.size()也在变化 ,因此此处不能 i++ (一定要注意) 最好还是用while(s.size > 0) 
			if(s[0] != '0'){
				break;
			}
			s.erase(s.begin());
			e--;
		}
	}else{ //数值 > 1时 
		for(int i = 0; i < s.size(); i++){
			if(s[i] == '.'){
				s.erase(s.begin() + i);
				break;
			}
			e++;
		}
	}
	if(s.size() == 0)
		e = 0;
	s = s.substr(0, n);
	while(s.length() < n){
		s += '0'; 
	}
		
}
int main(){
	string a, b;
	int e1 = 0, e2 = 0;
	cin >> n >> a >> b;
	del(a, e1);
	del(b, e2);
	if(a == b && e1 == e2)
		printf("YES 0.%s*10^%d\n", a.c_str(), e1);
	else
		printf("NO 0.%s*10^%d 0.%s*10^%d\n", a.c_str(), e1, b.c_str(), e2);
	return 0;
}

参考柳神代码思路: 通过char类型数组实现小数保留:

https://blog.csdn.net/liuchuo/article/details/52262703

思路:

/**
细心最后输出时 输出的是A数组
思路:

主要是设置 为 a,b字符串分别设置4个游标(可以假设为指针)

主要是定义 p, q, cnta, cntb (p, cnta是一组, q, cntb 是一组)

q指向 a字符串中第一个非0 非 .的数字

cnta 默认长度为 strlen(a)

1. 当cnta > p时 这时 就可以得出 指数a为 cnta - p;

2. 当cnta  < p时 这时 就可以得出 指数a为 cntb - p + 1;

3. 当cnta == p时 这时就是特殊情况0的时候, 指数a为0

最终保留小数时, 以p为下标遍历a数组(此步就去除了前导0), 将a数组中的值赋值给A数组, 如果 A数组中的长度不满足 n位

就在A数组后补0;
**/

具体代码实现:

#include<iostream>
#include<cstring>
using namespace std;
const int maxsize = 1e4 + 5; 
int main(){
	char a[maxsize], b[maxsize], A[maxsize], B[maxsize];
	int n,cnta, cntb, eA, eB, p = 0, q = 0;
	 scanf("%d%s%s", &n, a, b);
//	cin >> n >> a >> b;
	int lengA = strlen(a); 
	int lengB = strlen(b);
	cnta = lengA;
	cntb = lengB; 
	for(int i = 0; i < lengA; i++){
			if(a[i] == '.'){
				cnta = i;
				break;
			}
	}
	for(int i = 0; i < lengB; i++){
		if(b[i] == '.'){
			cntb = i;
			break;
		}
	}
	while(a[p] == '0' || a[p] == '.') p++;
	while(b[q] == '0' || b[q] == '.') q++;
	if(cnta >= p) 
		eA = cnta - p;
	else
		eA = cnta - p + 1;
	if(cntb >= q)
		eB = cntb - q;
	else
		eB = cntb - q + 1;
	if(p == lengA)
		eA = 0;
	if(q == lengB)
		eB = 0;
	int indexA = 0, indexB = 0;
	while(indexA < n){
		if(p < lengA && a[p] != '.')
			A[indexA++] = a[p];
		else if(p >= lengA)
			A[indexA++] = '0';
		p++;
	}
	while(indexB < n){
		if(q < lengB && b[q] != '.')
			B[indexB++] = b[q];
		else if(q >= lengB)
			B[indexB++] = '0';
		q++;
	}
	if(strcmp(A, B) == 0 && eA == eB)
		printf("YES 0.%s*10^%d\n", A, eA);
	else
		printf("NO 0.%s*10^%d 0.%s*10^%d\n",A, eA, B, eB); 
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值