大数运算(5)——大数除法(取模、取余)

本文介绍了一种处理大数除法的方法,通过逐步减少被除数来计算商和余数,适用于大数间的除法运算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有关于大数除法的运算可以大致分为两种:一种是求商(取模),另一种是求余数(取余)。

有两个大整数a和b,当a==b时,a/b==1,余数是0。(a!=0,b!=0)

                                     当a>b时,a/b>=1,余数需要通过计算求得。

                                     当a<b时,a/b=0,余数就是a。

而我们经常需要求的便是当a>b,这种情况我们该如何求商和余数呢?

其实基本的思想就是反复做减法,看看从被除数里最多能减去多少个除数,商就是多少。一个一个减显然太慢,如何减得更快一些呢?

以28536 除以23 为例来看一下:开始商为0。

先减去23 的1000 倍,就是23000,发现够减1 次,余下5536,于是商的值就增加1000;

然后用5536减去2300,发现够减2 次,余下936,于是商的值增加200,即1200;

再用936 减去230,够减4 次,余下16,于是商值增加40,即1240。

最后,发现余下的数比23小,即为余数,即28536 / 23 得1240余16。

这时,你会发现这其实就是咱们人工计算时相当于列的竖式。

另外,注意:我这里写的是有关大数除以大数的除法,同样适用于大数除以int类型范围的数,当然,也可以另写关于大数除以int的数。

这里写的全部是大整数,不包括小数。

下面是C语言代码实现:

#include<stdio.h>  
#include<string.h>  
char a[100],b[100];//用两个字符串用来输入两个大数   
int x[100],y[100],z[100],m[100];//被除数  除数  商  余数   
int digit;//大数的位数   
void sub(int x[],int y[],int len1,int len2)//大数减法   
{  
    int i;  
    for(i=0;i<len1;i++)  
    {  
        if(x[i]<y[i])  
        {  
            x[i]=x[i]+10-y[i];  
            x[i+1]--;  
        }  
        else  
            x[i]=x[i]-y[i];  
    }  
    for(i=len1-1;i>=0;i--)//判断减法结束之后,被除数的位数   
    {  
        if(x[i])  
        {   
            digit=i+1;  
            break;           
        }   
    }  
}  
int judge(int x[],int y[],int len1,int len2)  
{  
    int i;  
    if(len1<len2)  
        return -1;  
    if(len1==len2)//若两个数位数相等   
    {  
        for(i=len1-1;i>=0;i--)  
        {  
            if(x[i]==y[i])//对应位的数相等   
                continue;  
            if(x[i]>y[i])//被除数 大于 除数,返回值为1   
                return 1;  
            if(x[i]<y[i])//被除数 小于 除数,返回值为-1   
                return -1;  
        }  
        return 0;//被除数 等于 除数,返回值为0   
    }     
}  
int main()  
{  
    int i,j=0,k=0,temp;  
    int len1,len2,len;//len两个大数位数的差值     
    while(~scanf("%s %s",a,b))  
    {  
        len1=strlen(a);//被除数位数  
        len2=strlen(b);//除数位数  
        for(i=len1-1,j=0;i>=0;i--)//将字符串中各个元素倒序储存在数组中   
            x[j++]=a[i]-'0';  
        for(i=len2-1,k=0;i>=0;i--)  
            y[k++]=b[i]-'0';              
        if(len1<len2)//当被除数位数 小于 除数位数时   
        {  
            printf("商是:0\n");  
            printf("余数是:");  
            puts(a);   
        }  
        else //当被除数位数 大于或者 除数位数时  
        {  
            len=len1-len2;//两个大数位数的差值  
            for(i=len1-1;i>=0;i--)//将除数后补零,使得两个大数位数相同。被除数:4541543329 除数:98745,加零后:9874500000   
            {  
                if(i>=len)  
                    y[i]=y[i-len];  
                else  
                    y[i]=0;  
            }  
            len2=len1;//将两个大数数位相同         
            digit=len1; //将原被除数位数赋值给digit   
            for(j=0;j<=len;j++)  
            {  
                z[len-j]=0;  
                while(((temp=judge(x,y,len1,len2))>=0)&&digit>=k)//判断两个数之间的关系以及位数与除数原位数的关系   
                {     
                    sub(x,y,len1,len2); //大数减法函数                  
                    z[len-j]++;//储存商的每一位  
                    len1=digit;//重新修改被除数的长度  
                    if(len1<len2&&y[len2-1]==0)        
                        len2=len1;//将len1长度赋给len2;                        
                }  
                if(temp<0)//若被除数 小于 除数,除数减小一位。例如:被除数:4541543329 除数:(原)98745,(加零后)9874500000,后退一位后:0987450000   
                {  
                    for(i=1;i<len2;i++)  
                        y[i-1]=y[i];  
                    y[i-1]=0;  
                    if(len1<len2)   
                        len2--;                                           
                }  
            }  
            printf("商是:");  
            for(i=len;i>0;i--)//去掉前缀0   
            {  
                if(z[i])  
                    break;  
            }  
            for(;i>=0;i--)  
                printf("%d",z[i]);  
            printf("\n");  
            printf("余数是:");  
            for(i=len1;i>0;i--)  
            {  
                if(x[i])  
                    break;  
            }  
            for(;i>=0;i--)  
                printf("%d",x[i]);  
            printf("\n");  
        }  
    }  
    return 0;  
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值