大数(高精度)问题 【一】

处理大数问题为什么用字符串数组接收数据又转存到整型数组?

整型数组接收单个数字是以空格或者回车作为结束符,大整数的输入过程是没有空格或回车的。

字符串数组实际存储的是一个字符对应的Ascll码值,9+8其实是9对应的Ascll码和8对应的Ascll码相加得到新的Ascll码,结果肯定不是17,因为Ascll码表中只有0~9。

为什么要倒叙转存进整型数组?
要留足进位空间。假如是正序存入的(括号内写数组下标)
9(0)8(1)9(2)+
9(0)8(1)8(2)9(3)
我们该如何使得这两个数的个位对齐呢?就算个位对齐成这种样子
9(1)8(2)9(3)+
9(0)8(1)8(2)9(3)
得到的结果也会因为进位而无法存储
1(-1)0(0)8(1)7(2)8(3) 

数组下标怎么可能为-1
如果我们是倒叙转存进整型数组的话,一切问题都可以迎刃而解
9(0)8(1)9(2) +
9(0)8(1)8(2)9(3)
8(0)7(1)8(2)0(3)1(4)
不仅个位对齐,由于全部是倒叙,向右进位也可以很好的解决。

首先对字符串的处理

void getDigits(int num[],char str[])//把字符串保存在int类型的数组中
{
    char digit;
    int len = strlen(str);
    for(int i=0; i<len; ++i)
    {
        digit=str[i];
        num[len-i-1]=digit-'0';//字符串倒叙保存
    }
}

大数加法

void add(int a[],int b[],int sum[])//同理大数加法
{
    for(int i=0; i<MAX; i++)
    {
        sum[i]=a[i]+b[i];
    }
    //将十位以上的数字向上进位,将剩余的数字保存在自己位置上
    for(int i=0; i<MAX; i++)
    {
        sum[1+i] += sum[i]/10;
        sum[i] = sum[i]%10;
    }
}

大数乘法

void multiply(int a[],int b[],int sum[])//大数乘法
{
    /*
    数组a和数组b逐位相乘,并把结果保存于数组sum
    12345*12345 5与12345中的每位相乘
    对于数组sum sum[i+j]在i=0,j=1,2,3,4,5时保存的是5和各位相乘的结果
    而在i=1,j=1,2,3,4,5时保存的是4和各位相乘的结果,并累加上次相乘的结果
    */
    for(int i=0; i<MAX; i++)
    {
        for(int j=0; j<MAX; j++)
        {
            sum[i+j] += a[i]*b[j];
        }
    }
    //将十位以上的数字向上进位,将剩余的数字保存在自己位置上

    for(int i=0; i<MAX*2-1; i++)
    {
        sum[1+i] += sum[i]/10;
        sum[i] = sum[i]%10;
    }
}

大数阶层

const int N = 200000;//大数阶层所需
int NUM[N];//大数阶层所需

void Rank(int n)//大数阶层
{
    memset(NUM,0,sizeof(NUM));
    int s=0,t=0;
    NUM[0]=1;
    for(int i=2; i<=n; i++)
    {
        for(int j=0; j<=s; j++)
        {
            NUM[j]=NUM[j]*i+t;
            t=NUM[j]/10000;
            NUM[j]=NUM[j]%10000;
        }
        while(t)
        {
            NUM[++s]=t%10000;
            t=t/10000;
        }
    }
    printf("%d",NUM[s]);
    for(int i=s-1; i>=0; i--)
        printf("%04d",NUM[i]);
    printf("\n");
}

完整的代码

#include <cstdio>
#include <iostream>
#include <cstring>
#include <sstream>
#define max(a,b) a>b?a:b
using namespace std;
const int N = 200000;//大数阶层所需
const int MAX = 1000;//根据题目要求定义MAX的大小
int NUM[N];//大数阶层所需
void getDigits(int num[],char str[])//把字符串保存在int类型的数组中
{
    char digit;
    int len = strlen(str);
    for(int i=0; i<len; ++i)
    {
        digit=str[i];
        num[len-i-1]=digit-'0';//字符串倒叙保存
    }
}
void multiply(int a[],int b[],int sum[])//大数乘法
{
    /*
    数组a和数组b逐位相乘,并把结果保存于数组sum
    12345*12345 5与12345中的每位相乘
    对于数组sum sum[i+j]在i=0,j=1,2,3,4,5时保存的是5和各位相乘的结果
    而在i=1,j=1,2,3,4,5时保存的是4和各位相乘的结果,并累加上次相乘的结果
    */
    for(int i=0; i<MAX; i++)
    {
        for(int j=0; j<MAX; j++)
        {
            sum[i+j] += a[i]*b[j];
        }
    }
    //将十位以上的数字向上进位,将剩余的数字保存在自己位置上

    for(int i=0; i<MAX*2-1; i++)
    {
        sum[1+i] += sum[i]/10;
        sum[i] = sum[i]%10;
    }
}
void add(int a[],int b[],int sum[])//同理大数加法
{
    for(int i=0; i<MAX; i++)
    {
        sum[i]=a[i]+b[i];
    }
    //将十位以上的数字向上进位,将剩余的数字保存在自己位置上
    for(int i=0; i<MAX; i++)
    {
        sum[1+i] += sum[i]/10;
        sum[i] = sum[i]%10;
    }
}
void Rank(int n)//大数阶层
{
    memset(NUM,0,sizeof(NUM));
    NUM[0] = 1;
    int p,h; //h表示当前结果的进位,p表示当前的位数
    p = 0;
    for(int i = 2; i <= n; i++)
    {
        h = 0;
        int j;
        for(j = 0; j <= p; j++)
        {
            NUM[j] = NUM[j] * i + h;
            h = NUM[j] / 10;
            NUM[j] = NUM[j] % 10;
        }
        while(h > 0)
        {
            NUM[j] = h % 10;
            h /= 10;
            j++;
        }
        p = j;
    }
    for(int i = p-2; i >= 0; i--)
    {
        printf("%d",NUM[i]);
    }
    printf("\n");
}
int main()
{
    char num1[MAX],num2[MAX];
    int a[MAX];
    int b[MAX];
    int sum[MAX*2];
    while(scanf("%s%s",&num1,&num2)!=EOF)//多组实例测试
    {
        if(strcmp(num1,"0")==0||strcmp(num2,"0")==0)
        {
            printf("0\n");
            continue;
        }
        getchar();  //吞回车 不可少(如果一组实例需要省略)
        memset(a,0,sizeof(a)); //初始化数组a,b
        memset(b,0,sizeof(b));
        memset(sum,0,sizeof(sum));
        getDigits(a,num1);
        getDigits(b,num2);
        multiply(a,b,sum);//大数加法时可以把函数名字改成add
        int j=MAX*2-1;
        while(sum[j]==0)
        {
            j--;
        }
        for(int i = j; i >= 0; i--)
        {
            printf("%d",sum[i]);
        }
        printf("\n");
        int num;
        cin>>num;
        Rank(num);//计算大数阶层
    }
    return 0;
}

需要根据题目要求对模板进行修改。

    原文作者:大整数乘法问题
    原文地址: https://blog.csdn.net/qq_36345036/article/details/60333680
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞