实数加法的一个解决思路

Posted zcsor

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实数加法的一个解决思路相关的知识,希望对你有一定的参考价值。

33:实数加法
查看 提交 统计 提问
总时间限制: 1000ms 内存限制: 65536kB
描述
求2个实数相加的和。

输入输出中出现的实数都有如下的形式: P1P2...Pi.Q1Q2...Qj。对于整数部分,P1P2...Pi是一个非负整数;对于小数部分,至少有一位且最后一位Qj不等于0。

输入
2行,分别是两个加数。每个加数不超过100个字符。
输出
一行输出是相应的和。数据保证一定是一个小数部分不为0的实数。
样例输入
0.111111111111111111111111111111
0.111111111111111111111111111111
样例输出
0.222222222222222222222222222222

这个问题交了好几次,漏打了一个按址传递,漏了一种情况。简要分析一下,这个题的要点就是:

1、小数点对齐

2、结尾0的处理

结尾0的处理这里开始漏了一种情况,只考虑了小数点之后的不要了,小数点之前的占位0没考虑。例如:1.2+8.8这样。小数点对齐倒是没什么问题,但是处理整数部分对齐的时候忘了一个&,调试半天。这个题最开始的思路是想从小数点开始,分别向左右取4位,保存到int[],然后对齐处理,发现挺烦人的,于是直接在字符串上处理:

1、获取小数点左右两部分,把右边较短的用0右补齐,把左边较短的用0左补齐。

2、从最低位开始逐个字符计算结果和进位,舍弃结尾0。(这里疏漏了,小数点之前的0不能舍弃)。

3、最高位计算之后如果有进位,在左侧添加一位。

4、插入小数点。

5、输出。

这种在字符串上直接处理的做法效率较低,如果时间比较少计算量比较大,那么一定要用int[]数组,一般可以采用万进制。但是这个题完全可以这样做,就像那个除以13的问题一样,都可以直接处理。

#include<iostream>
#include<cstring>
using namespace std;
inline void zx(string v,string &z,string &x){    //分离整数和小数部分
    int i;
    i=v.find(".");
    z=v.substr(0,i);
    x=v.substr(i+1,v.size()-1);
}
inline void xadd(string &x1,string &x2){        //将小数部分较短的填充0以对齐
    if(x1.size()>x2.size()){
        x2+=string(x1.size()-x2.size(),0);
    }else{
        x1+=string(x2.size()-x1.size(),0);
    }
}
inline void zadd(string &z1,string &z2){        //将整数部分较短的填充0以对齐
    if(z1.size()>z2.size()){
        z2=string(z1.size()-z2.size(),0)+z2;
    }else{
        z1=string(z2.size()-z1.size(),0)+z1;
    }
}
int main(){
    string s1,s2,z1,x1,z2,x2,result;
    cin>>s1>>s2;
    zx(s1,z1,x1);    //整体思路就是按小数点对齐,两侧短的用0补充。这样就可以从低位一直计算到高位。
    zx(s2,z2,x2);
    zadd(z1,z2);
    xadd(x1,x2);
    s1=z1+x1;            //此时的s1,s2完全对齐,算法可以得到简化。
    s2=z2+x2;
    int i,cur,up=0,rightzeroflag=1;
    for(i=int(s1.size())-1;i>=0;i--){
        cur=s1[i]-0+s2[i]-0+up;        //当前位的总和
        if(i<int(z1.size())){            //小数点后面的不计入,但是过了小数点就需要占位了。
            rightzeroflag=0;
        }
        if(cur%10==0 && rightzeroflag==1){    //末尾多余的0不计入。
        }else{
            rightzeroflag=0;
            result=char(cur%10+0)+result;    //计入当前位的值
        }
        up=cur/10;
    }
    cur=z1.size();    //整数部分的大小,确定小数点位置。
    if(up!=0){        //如果最高位计算之后需要进位
        result=char(up+0)+result;
        cur++;
    }
    if(cur<int(result.size())){    //如果整数部分大小比返回值小,说明有小数部分。
        result.insert(cur,".");
    }
    cout<<result<<endl;
}

这个代码好处就在于不用考虑多少位,怎么对齐的问题。还是对C++有一种排斥感,实际上截取字符串也很简单,但就是感觉别扭。

以上是关于实数加法的一个解决思路的主要内容,如果未能解决你的问题,请参考以下文章

noi1_13_48[实数加法]

指针作业

数学上的R代表啥数

DSP5509项目之用FFT识别钢琴音调

C++,构造一个读取两个实数和一个字符的程序

泉州一中复赛模拟