1060 Are They Equal

题意:

给出两个浮点数(最大不超过10^100),以及存储的有效位数,判断这两个数是否相等。如12300和12358.9若存储的有效位数为3,则均表示为0.123*10^5,因此视为相等。

思路:【字符串处理】

这一题是以科学计数法为背景的字符串处理问题。首先,题目中明确数值大小的范围在10^100,因此属于大整数问题,用字符串string存储。·其次,对于任意一个数,科学计数法的表示为: 0.d[1]...d[N]*10^k  其中d[1]>0,除非这个数本身就是0,即数值0存储为:0.000*10^0(假设有效位数是3)。若要比较两个数是否相等,只需要比较两个方面,即有效位数部分 d[1]...d[N] 和指数部分 k 是否都相等,只有在两部分都相等的情况下,才判定这两个数相等。因此,问题的关键是如何求出这两个部分。

样例给出情况太少,需要自己考虑更多的情况,如:(假设有效位数都是3)

000 0000   YES 0.000*10^0

000 0.00    YES 0.000*10^0

0012300 12358.9   YES 0.123*10^5

0.001200 1.2   NO 0.120*10^-2  0.120*10^1

分析:

首先,不管给出的数是小数还是整数,需要先排除是否存在前导0,因为在数值表示中00123和123,0000.168和0.168是一样的,所以在真正的逻辑处理前先要排除这样的干扰(这是处理数值问题常见的,默认应该考虑到的坑);

其次,具体到本题,我们把情况分为整数部分小于0和大于0的情况(为什么会这么考虑,因为如31.4,其科学计数法的指数部分是2;而0.00314,其科学计数法的指数部分是-2,一正一负)。整数部分小于0的,如 0.00301400 ,在处理完前导0后就变成了 .00301400 ,其中小数部分首个非0数字之前的0的个数的相反数就是这个值科学计数法的指数exp,我们可以遍历这部分字符串,若当前字符为0,则exp--,遇到第一个非0字符就退出。然后在剩下的部分截取(或者补0)出n个有效位数即可。需要特别注意的是, 0.000 这种情况,其对应的exp是0,要单独考虑;整数部分大于0的,又分为存在小数和不存在小数两种情况,如 12300 和 12358.9 ,思路是先寻找是否存在小数点,若有小数点的,则把小数点删掉再截取(或者补0)出n个有效位数即可。需要特别注意的是, 0000 这种情况,其对应的exp=0,要特别考虑。

对于字符串处理的问题,往往实现起来比较麻烦,可能要考虑很多边界情况,耗时较长,代码写的也像是一坨**一样,道阻且长,慢慢修炼!

代码:

#include <iostream>
#include <string>
using namespace std;

int n;//有效位数

//exp传入时为0
string change(string str,int& exp)
{
    string significantPart;
    //删除可能存在的前导0,当至少保留一位
    while(str.size()>1 && str[0]=='0')
        str.erase(str.begin());
    if(str[0]=='.'){//整数部分为0
        str.erase(str.begin());
        while(str.size()>0 && str[0]=='0'){
            exp--;
            str.erase(str.begin());
        }
        if(str.size()==0) exp=0;//特别处理,如0.000
        if(str.size()>=n) significantPart=str.substr(0,n);
        else significantPart=str+string(n-str.size(),'0');
    }else{//整数部分不为0
        int pointPos=str.find(".");
     //注意这么写是错的
     //if(pointPos==-1 && str[0]!='0') exp=str.size();//ERROR!
if(pointPos==-1) { if(str[0]!='0') exp=str.size();//特殊处理,需要考虑值就是0的情况,当且仅当str不为0时,exp才等于其size;对于0而言,exp统一为0,因为exp传入时为0,故不用在此处理 }else { exp=pointPos; str.erase(pointPos,1); } if(str.size()>=n) significantPart=str.substr(0,n); else significantPart=str+string(n-str.size(),'0'); } return significantPart; } int main() { string str_a,str_b; cin>>n>>str_a>>str_b; int exp_a=0,exp_b=0; string ans_a=change(str_a,exp_a); string ans_b=change(str_b,exp_b); if(ans_a==ans_b && exp_a==exp_b){ cout<<"YES "<<"0."<<ans_a<<"*"<<"10^"<<exp_a; }else{ cout<<"NO"; cout<<" 0."<<ans_a<<"*"<<"10^"<<exp_a; cout<<" 0."<<ans_b<<"*"<<"10^"<<exp_b; } return 0; }

 

转载于:https://www.cnblogs.com/kkmjy/p/9536759.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值