高精度除法

       算法主体来自:http://blog.csdn.net/jarily/article/details/8623810,我做了一些错误的改正以及加了一些注释。最后,把C风格改成了C++风格(我真无聊....)。

   算法思想:反复做减法,看看从被除数里最多能减去多少个除数,商就是多少。所以算法核心是写一个大整数的减法函数,反复调用该函数进行减法操作。

   算法步骤:用数组a表示被除数,数组b表示除数,数组res表示商;先用被除数a减去除数b得到差的位数k,同时商+1,再用被除数a减去若干个除数b*(10^k),不够减了,再减去若干个除数b*(10^(k-1))...b*(10^(k-2))...,一直减到不够减为止;每成功减一次,则商的相应位+1;最后再循环处理商的进位问题。

#include<iostream>  
#include<cstring>  
#include<cstdlib>  
#include<cstdlib>  
using namespace std;  
  
const int N=1000;  
int a[N],b[N],res[N*2];  
char x[N],y[N];  
int len1,len2;  
  
void init()  
{  
    len1=strlen(x);  
    len2=strlen(y);  
    memset(a,0,sizeof(a));  
    memset(b,0,sizeof(b));  
    memset(res,0,sizeof(res));  
    for(int i=len1-1,j=0; i>=0; i--) //将被减数转为数字倒序存储在数组中,便于进行计算 
    {  
        a[j++]=x[i]-'0';  
    }  
    for(int i=len2-1,j=0; i>=0; i--)  //将减数转为数字倒序存储在数组中,便于进行计算 
    {  
        b[j++]=y[i]-'0';  
    }  
}  
  
int substraction(int *p1,int *p2,int len1,int len2)//计算长度为len1的大整数减去长度为len2的大整数的结果的长度  
{                                                  //减的结果放在数组p1中,不够返回-1,正好返回0  
    if(len1<len2)  
        return -1;  
    bool flag=0;  
    if(len1==len2)//若两数长度相等,一位位判断大小  
    {  
        for(int i=len1-1; i>=0; i--)  
        {  
            if(p1[i]>p2[i])  
                flag=1;  
            else if(p1[i]<p2[i])  
            {  
                if(!flag)  
                    return -1;  
            }  
        }  
    }  
  
    for(int i=0; i<len1; i++)//减法  
    {  
        p1[i]-=p2[i];  
        if(p1[i]<0)  
        {  
            p1[i]+=10;  
            p1[i+1]--;  
        }  
    }  
    for(int i=len1-1; i>=0; i--)  
    {  
        if(p1[i])  //光标遍历至非零处(忽略开头的0)
            return i+1;  //返回最高位非零位的前一位位置,即新的被减数长度
    }  
    return 0;  
}  
  
void output()  
{  
    for(int i=0; i<N; i++) //进位  
    {  
        if(res[i]>=10)  
        {  
            res[i+1]+=res[i]/10;  
            res[i]%=10;  
        }  
    }  
  
    bool flag=0;  
    for(int i=N-1; i>=0; i--)//输出  
    {  
        if(flag)    
        {  
            cout<<res[i];  
        }  
        else if(res[i])  //遇到第一个非零数才开始输出操作
        {  
            cout<<res[i];  
            flag=1;  
        }  
    }  
    if(!flag)  //如果一直都是0,就输出一个0
       cout<<0; 
    cout<<endl;  
}  
  
void solve()  
{  
    init();  
    
    len1=substraction(a,b,len1,len2);//被减数减去减数后得到的差为新的被减数,得到新的被减数长度
    if(len1<0)  
    {  
        cout<<0<<endl; 
        return;  
    }  
    else if(len1==0)  
    {  
        cout<<1<<endl;  
        return;  
    }  
  
    res[0]++;//减掉一次了,商+1  
    int k=len1-len2;  
    if(k<0)//减一次后不能再减了  
    {  
        output();  
        return;  
    }  
    else if(k>0)//将数组b乘以10的某次幂(通过使数组整体左移动,后端添0实现),使得其长度与数组a相同  
    {  
        for(int i=len1-1; i>=0; i--)  
        {  
            if(i>=k)  
                b[i]=b[i-k];  
            else  
                b[i]=0;  
        }  
    }  
  
    len2=len1;  
    for(int j=0; j<=k; j++)//先减去若干个b*(10^k),不够减了再减去若干个b*(10^(k-1))...  
    {  
        int temp;  
        while((temp=substraction(a,b+j,len1,len2-j))>=0)//一直减到不够减为止  
        {  
            len1=temp;  
            res[k-j]++;//每成功减一次,则商的相应位+1  
        }  
    }  
    output();  
}  
  
int main()  
{  
    
        cin>>x>>y;  
        solve();  
		system("pause");  
    return 0;  
}  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值