OpenJudge NOI 1.13 33:实数加法 | 1.13 48:实数加法

【题目链接】

OpenJudge NOI 1.13 33:实数加法
OpenJudge NOI 1.13 48:实数加法

【题目考点】

1. 高精度

【解题思路】

解法1:使用数组、函数

将输入的数字根据’.'来分成前后两部分,前面是整数部分,后面是小数部分。
a[i]表示整数部分小数点前第i位的数字,an为小数点前数字个数。b[i]表示小数点后第i位的数字,bn为小数点后数字个数。将第1个实数分解成a1,b1两个数组,将第2个实数分解成a2,b2两个数组。
先让b1与b2做高精度加法,相加的末位为b1与b2长度的最大值,从这一位开始不断相加,结果保存在b3,进位为c。
也许末位相加后结果为0,会导致小数点后的位数bn变少。所以只要bn指向的位置为0,就向前移动。
保留进位c,参与整数部分的相加。让a1与a2相加得到a3,得到的结果可能会超出a1与a2的最大长度。
最后输出a3,点,b3。

解法2:写高精度实数类

用类表示一个实数,包含属性:整数部分数字数组a,长度an;小数部分数字数组b,长度bn。解题思路与解法1相同,但用类来写代码更有层次,读起来更清晰。推荐写类来解决问题。

【题解代码】

解法1:使用数组、函数
#include <bits/stdc++.h>
using namespace std;
#define N 105
int getA(char s[], int p, int a[])
{
    int an = 0;
    for(int i = p-1; i >= 0; --i)
        a[++an] = s[i]-'0';
    return an;
}
int getB(char s[], int p, int b[])
{
    int bn = 0, len = strlen(s);
    for(int i = p+1; i < len; ++i)
        b[++bn] = s[i]-'0';
    return bn;
}
int getP(char s[])
{
    int len = strlen(s);
    for(int i = 0; i < len; ++i)
        if(s[i] == '.')
            return i;
}
char s[N];
int a1[N], b1[N], a2[N], b2[N], a3[N], b3[N], an1, an2, an3, bn1, bn2, bn3;
int main()
{    
    cin >> s;
    int p = getP(s);
    an1 = getA(s, p, a1);
    bn1 = getB(s, p, b1);
    cin >> s;
    p = getP(s);
    an2 = getA(s, p, a2);
    bn2 = getB(s, p, b2);   
    bn3 = max(bn1, bn2);
    int c = 0;
    for(int i = bn3; i >= 1; --i)
    {
        b3[i] = b1[i]+b2[i]+c;
        c = b3[i]/10;
        b3[i] %= 10;
    }
    while(b3[bn3] == 0)
        bn3--;
    an3 = max(an1, an2);
    for(int i = 1; i <= an3; ++i)
    {
        a3[i] = a1[i]+a2[i]+c;
        c = a3[i]/10;
        a3[i] %= 10;
    }
    if(c > 0)
        a3[++an3] = c;
    for(int i = an3; i >= 1; --i)
        cout << a3[i];
    cout << '.';
    for(int i = 1; i <= bn3; ++i)
        cout << b3[i]; 
    return 0;
}
解法2:写高精度实数类
#include <bits/stdc++.h>
using namespace std;
#define N 105
struct RealNum
{
    int a[N], b[N];//a[i]:小数点前第i位 b[i]:小数点后第i位
    int an, bn;//an:小数点前有几位 bn:小数点后有几位 
    RealNum(){}
    RealNum(string s)
    {
        memset(a, 0, sizeof(a));
        memset(b, 0, sizeof(b));
        an = bn = 0;
        int p = 0;
        while(s[p] != '.')
            p++;
        for(int i = p-1; i >= 0; --i)
            a[++an] = s[i] - '0';
        for(int i = p+1; i < s.length(); ++i)
            b[++bn] = s[i] - '0';
    }
    void operator += (RealNum x)//自己加上x 
    {
        int c = 0;
        bn = max(bn, x.bn);
        for(int i = bn; i >= 1; --i)
        {
            b[i] = b[i] + x.b[i] + c;
            c = b[i]/10;
            b[i] %= 10;
        }
        while(b[bn] == 0)
            bn--;
        an = max(an, x.an);
        for(int i = 1; i <= an; ++i)
        {
            a[i] = a[i] + x.a[i] + c;
            c = a[i]/10;
            a[i] %= 10;
        }
        if(c > 0)
            a[++an] = c;    
    }
    void show()
    {
        for(int i = an; i >= 1; --i)
            cout << a[i];
        cout << '.';
        for(int i = 1; i <= bn; ++i)
            cout << b[i];
    }
};
int main()
{
    string s1, s2;
    cin >> s1 >> s2;
    RealNum r1(s1), r2(s2);
    r1 += r2;
    r1.show(); 
    return 0;
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值