大数运算——加减乘除

大数运算产生的原因就是因为int,double类型表示范围都有限,无法表示过长的数字比如:2345468454567865415467864453437。
因此也就无法进行四则运算,为了实现这种运算,大数运算产生了。
其实也很简单,既然基本数据类型放不下这些数据,那就用数组存放呗。
定义char c[100000000],总能放下这么大的数了吧,当然因为这些数是用数组保存的,那么对它们进行运算也就不能简单的加减乘除了。只能通过模拟人工计算的方法来实现。

大数运算最难的在于除法的运算,其他的加减乘都是模拟人的计算方法。

如果模拟人工的计算方法来计算除法,emm....怎么模拟,貌似不太简单。
所以除法就是将除法转换为减法来运算。 例如计算6/2,可以转换为计算6-2能减多少次,很显然,能减三次,所以答案就出来了。为3。

废话不多说 上代码。
#include<stdio.h>
#include<string.h>
#define max(a,b) (a>b?a:b)
//比较两个字符串数值,前者大返回正数,相等返回0,前者小负数;
int compare(char *a,char *b)
{
    if(strlen(a)>strlen(b))
        return 1;
    else if(strlen(a)<strlen(b))
        return -1;
    else return strcmp(a,b);
}
void add(char *a,char *b,char *num)//加法
{
    int flag;
    int j1=0;
    char num1[100000]= {0},num2[100000]= {0};
    /* 逆序存放a,b 且将ascll码转为0-9*/
    for(int i=strlen(a)-1,j=0; i>=0; i--,j++)
        num1[i]=a[j]-48;
    for(int i=strlen(b)-1,j=0; i>=0; i--,j++)
        num2[i]=b[j]-48;

    for(int i=0; i<max(strlen(a),strlen(b))+1; i++)
        if(num1[i]+num2[i]>9)//相加>9,向高位进位
        {
            num1[i+1]++;
            num1[i]=num1[i]+num2[i]-10;
        }
        else num1[i]+=num2[i];
    for(flag=99999; num1[flag]==0; flag--);
    for(int i=flag; i>=0; i--,j1++)//将结果转回正序,且转换回ascll码
    {
        num[j1]=num1[i]+48;
    }
    num[j1]='\0';
}
void sub(char *a,char *b,char *num)//减法
{
    int flag;
    int j1=0;
    char num1[100000]= {0},num2[100000]= {0};
    //如果a<b,将a b互换,并且输出负号
    if(compare(a,b)<0)
    {
        printf("-");
        //同加法
        for(int i=strlen(b)-1,j=0; i>=0; i--,j++)
            num1[i]=b[j]-48;
        for(int i=strlen(a)-1,j=0; i>=0; i--,j++)
            num2[i]=a[j]-48;
    }
    else
    {
        for(int i=strlen(a)-1,j=0; i>=0; i--,j++)
            num1[i]=a[j]-48;
        for(int i=strlen(b)-1,j=0; i>=0; i--,j++)
            num2[i]=b[j]-48;
    }

    for(int i=0; i<strlen(a); i++)
    {
        if(num1[i]-num2[i]<0)//<0,向高位借位
        {
            num1[i+1]--;
            num1[i]=num1[i]-num2[i]+10;
        }
        else num1[i]-=num2[i];
    }
    for(flag=99999; num1[flag]==0&&flag>0; flag--);
    if(compare(a,b)<0)
        num[j1]='-',j1++;
    for(int i=flag; i>=0; i--,j1++)
    {
        num[j1]=num1[i]+48;
    }
    num[j1]='\0';
}
void mul(char *a,char *b,char *num)//乘法
{
    int flag;
    int j1=0;
    char mu=0,ad=0;//mu积进位,ad和进位
    char result[200000]= {0};
    char num1[100000]= {0},num2[100000]= {0};
    /* 逆序存放a,b 同加法*/
    for(int i=strlen(a)-1,j=0; i>=0; i--,j++)
        num1[i]=a[j]-48;
    for(int i=strlen(b)-1,j=0; i>=0; i--,j++)
        num2[i]=b[j]-48;
        /*核心部分
        *将已有result[i+j]与当前计算出的result[i+j]相加,并且和 进位
        *计算当前result[i+j],并且记录积进位,!!!!注意:积进位不能直接进位,要先记录下,下次计算再进位。
        *模拟人工乘法
        */
    for(int i=0; i<strlen(a)+1; i++)
        for(int j=0; j<strlen(b)+1; j++)
        {
            flag=num1[i]*num2[j]+mu;
            mu=flag/10;
            if(result[i+j]+flag%10>9)
            {
                result[i+j+1]++;
                result[i+j]=result[i+j]+flag%10-10;
            }
            else
            result[i+j]=result[i+j]+flag%10;
        }
    for(flag=99999; result[flag]==0&&flag>0; flag--);
    for(int i=flag; i>=0; i--,j1++)
    {
        num[j1]=result[i]+48;
    }
    num[j1]='\0';
}
/*
大数除法原理:反复做减法,看从被除数里面最多能减去多少个除数,商就是多少。
逐个减显然太慢,要判断一次最多能减少多少个整的10的n次方。
以7546除23为例。
先减去23的100倍,就是2300,可以减3次,余下646。   此时商就是300;
然后646减去23的10倍,就是230,可以减2次,余下186。此时商就是320;
然后186减去23,可以减8次,此时商就是328.
*/
void div(char *a,char *b,char *num)//除法
{
    if(compare(a,b)<0)//a<b
    {
        num[0]='0';
        num[1]='\0';
    }
    else if(compare(a,b)==0)//a==b
    {
        num[0]='1';
        num[1]='\0';
    }
    else  //a>b
    {
        int j=0;
        memset(num,48,200000);//20000为数组大小
        char num1[100000]= {0},num2[100000]= {0};
        strcpy(num1,a);
        int alength=strlen(a),blength=strlen(b);
        int divalue=alength-blength;//两个数据相差的位数
        while(divalue>=0)
        {
            int i=0;
            strcpy(num2,b);
            num2[blength+divalue]='\0'; //将b放大为与a位数相同
            for( ;i<divalue; i++)
                num2[blength+i]='0';
            while(compare(num1,num2)>=0) //a b相减 直到a<b
            {
                sub(num1,num2,num1);
                num[j]++;
            }
            divalue--;
            j++;
        }
        num[j]='\0';
        if(num[0]==48)//去除首位的0
           strcpy(num,num+1);
    }
}
int main()
{
    char a[100000],b[100000],result[200000];
    scanf("%s%s",a,b);
    add(a,b,result);
    printf("\n+:%s",result);
    sub(a,b,result);
    printf("\n-:%s",result);
    mul(a,b,result);
    printf("\n*:%s",result);
    div(a,b,result);
    printf("\n/:%s",result);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/afra_bd/article/details/78994390