高精度计算-大整数加减法

问题描述

求两个不超过 200 位的非负整数的和。
输入数据
有两行,每行是一个不超过 200 位的非负整数,没有多余的前导 0。
输出要求
一行,即相加后的结果。结果里不能有多余的前导 0,即如果结果是 342,那么就不能
输出为 0342。

输入样例
22222222222222222222
33333333333333333333
输出样例
Output Sample:
55555555555555555555

解题思路

C/C++中的 int 类型能表示的范围是[ 231 , 2311 ]。
unsigned 类型能表示的范围是 [0, 2321 ]。所以,int 和 unsigned 类型变量,都不能保存超过 10 位的整数。( 10x<=2321,x<=9.63 )。参与运算的数如果大于10位数,基本数据类型已经无法表示。基本思想是:用数组模拟大整数,一个数组元素,放一位整数。不过一个数组元素存一位,空间上有点浪费,那么节省空间,可以一个数组存多位,比如说4位,注意的是进位的时候,这个时候的进位不再是10,而是10000。

代码实现

基本方法
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAX_LEN 200
int x[MAX_LEN + 20], y[MAX_LEN + 20], z[MAX_LEN + 20];
char a[MAX_LEN + 20], b[MAX_LEN + 20];

void char_to_int(const char s[ ], int x[ ])
{
    int i = 0;
    int len = strlen(s);

    memset(x,0,MAX_LEN + 20);  
    int j  = 0;
    for(i = len - 1; i >= 0; i--)
    {
        x[j++] = s[i] - '0';
    }
}

void big_int_add(const int x[], const int y[], int z[])
{
    int i = 0;
    memset(z,0,MAX_LEN + 20);  

    for(i = 0; i < MAX_LEN; i++)
    {
        z[i] += x[i] + y[i];
        if(z[i] >=10)
        {
            z[i] = z[i] - 10;
            z[i+1] ++; 
        }
    }
}

void big_int_print(const int z[])
{
    bool flag = 0;
    int i = 0;

    for(i = MAX_LEN; i >=0; i--)
    {
        if(flag)
            printf("%d",z[i]);
        else if(z[i])
        {
            printf("%d",z[i]);
            flag = 1;
        }
    }

    if(!flag)
        printf("0");
    printf("\n");
}


int main( )
{
    scanf("%s",a);
    scanf("%s",b);

    char_to_int(a,x);
    char_to_int(b,y);

    big_int_add(x,y,z);

    big_int_print(z);

    return 0;



}
方法二
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#define Radix_Len  4
#define  Carry_num  10000
#define MAX_LEN  (200 / Radix_Len + 1)
int x[MAX_LEN], y[MAX_LEN], z[MAX_LEN + 1];
char a[MAX_LEN ], b[MAX_LEN ];

void char_to_int(const char s[ ], int x[])
{
    int i = 0;
    int len = strlen(s);

    memset(x,0,MAX_LEN);  
    int j  = 0;
    for(i = len; i > 0; i -= Radix_Len)
    {
        int tmp , k ;
        tmp = 0;
        const int low = i - Radix_Len > 0 ? i - Radix_Len : 0;
        for(k = low; k < i; k++)
            tmp = tmp * 10 + ( s[k] - '0');
        x[j++] = tmp;
    }
}

void big_int_add(const int x[], const int y[], int z[])
{
    int i = 0;
    memset(z,0,MAX_LEN);  

    for(i = 0; i < MAX_LEN; i++)
    {
        z[i] += x[i] + y[i];
        if(z[i] >=Carry_num)
        {
            z[i] = z[i] - Carry_num;
            z[i+1] ++; 
        }
    }
}

void big_int_print(const int z[])
{
    bool flag = 0;
    int i = 0;

    for(i = MAX_LEN; i >=0; i--)
    {
        if(flag)
            printf("%d",z[i]);
        else if(z[i])
        {
            printf("%d",z[i]);
            flag = 1;
        }
    }

    if(!flag)
        printf("0");
    printf("\n");
}


int main( )
{
    scanf("%s",a);
    scanf("%s",b);

    char_to_int(a,x);
    char_to_int(b,y);

    big_int_add(x,y,z);

    big_int_print(z);

    return 0;



}

题目来自 OpenJudge 百练 http://bailian.openjudge.cn/practice/2981/

大整数减法

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAX_LEN 200
int x[MAX_LEN + 20], y[MAX_LEN + 20], z[MAX_LEN + 20];
char a[MAX_LEN + 20], b[MAX_LEN + 20];

void char_to_int(const char s[ ], int x[ ])
{
    int i = 0;
    int len = strlen(s);

    memset(x,0,MAX_LEN + 20);  
    int j  = 0;
    for(i = len - 1; i >= 0; i--)
    {
        x[j++] = s[i] - '0';
    }
}

void big_int_sub(const int x[], const int y[], int z[], int max_len)
{
    int i = 0;
    memset(z,0,MAX_LEN + 20);  

    int exchange = 0;

    printf("%d %d\n",x[max_len - 1],y[max_len - 1]);

    if(x[max_len - 1 ] < y[max_len - 1])
    {
        exchange = 1;
        printf("-");
    }
    for(i = 0; i < MAX_LEN; i++)
    {
        if(exchange)
        {
            z[i] += y[i] - x[i];
        }
        else
        {
            z[i] += x[i] - y[i];
        }

        if(z[i] < 0)
        {
            z[i] = z[i] + 10;
            z[i+1] --; 
        }
    }
}

void big_int_print(const int z[])
{
    bool flag = 0;
    int i = 0;

    for(i = MAX_LEN; i >=0; i--)
    {
        if(flag)
            printf("%d",z[i]);
        else if(z[i])
        {
            printf("%d",z[i]);
            flag = 1;
        }
    }

    if(!flag)
        printf("0");
    printf("\n");
}


int main( )
{
    scanf("%s",a);
    scanf("%s",b);

    int max_len = 0;
    int len1  = strlen(a);
    int len2  = strlen(b);

              max_len = len1 > len2 ? len1: len2;

    char_to_int(a,x);
    char_to_int(b,y);

    big_int_sub(x,y,z,max_len);

    big_int_print(z);

    return 0;



}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值