高精度除以高精度

本人大一新生一枚 寒假训练时遇到高精度这题一开始用滚动减法 T了十发 在其他人的博客上看到说要把除数扩大才行 但是其他大神写的代码实在看的是云里雾里 自己就用自己理解的方式写了一遍 正好有写个博客的打算 因为我的目标是星辰大海嘛 总得为后人留下点什么  代码排版有点丑 第一次写见谅。。。。

核心思想

只用单纯的减法去模拟除法肯定是会T的比如3000000/1
那么我们就需要将除数扩大到能除的极限就可以最大限度的优化
比如上述例子我们可以将 1 扩大到 1000000 就只需要减3次就可达到目的
再比如 12345/45:

i= 3     12345 < 45000    可以减 0个   shang[3]= 0      减后A: 12345
i=2     12345 < 4500      可以减 2个   shang[ 2]= 2      减后A: 3345
i= 1     3345  < 450         可以减 7个   shang[ 1]= 7      减后A: 195
i= 0     195   < 45            可以减 4个   shang[ 0]= 4      减后A: 15
总次数等于 0*10^3+2*10^2+7*10^1+4*10^0=274
仅仅减了2+7+4=13次,而非274
例子转自 https://www.cnblogs.com/lfyzoi/p/6737761.html

#include<stdio.h>
#include<string.h>
char n[1000],m[1000];
int a[1000],b[1000];
int s[1000];
int lena,lenb;
void add(int t)
{
    int i,r=0,p;
    s[t]+=1;   //扩大了多少倍的除数 就增加10的多少次方  不要用pow 因为int存不下!
    for(i=0;i<=lena;i++) 
    {
        p=s[i]+r;
        r=p/10;
        s[i]=p%10;
    }
}
int cp()
{
    int i;
    for(i=lena;i>=0;i--)
    {
        if(a[i]>b[i])         //判断除数是否小于被除数
           return 1;
     else if(a[i]<b[i])
           return 2;

    }
    return 0;                    //一定要有这个!如果除数等于被除数会出错!

}
int main()
{


    int i,j,z;
    while(scanf("%s%s",n,m)!=EOF)
    {
       memset(a,0,sizeof(a));
       memset(b,0,sizeof(b));
       memset(s,0,sizeof(s));
       lena=strlen(n);
       lenb=strlen(m);
       for(i=lena-1,j=0;i>=0;i--,j++)    //倒着输入进去方便减法           
       a[j]=n[i]-'0';
       for(i=lenb-1,j=lena-lenb;i>=0;i--,j++)    //很重要的一步 将除数扩大到能除的极限 
       b[j]=m[i]-'0';                                                                                                                         
       if(strcmp(n,m)==0)                //合理排除 除数相同的情况
       {                                 //注意除数为0的情况
           if(n==0)
            printf("0");
           else
           printf("1\n");
           printf("0\n");
           continue;
       }
       else if(strlen(m)>strlen(n)||strcmp(n,m)<0&&strlen(n)==strlen(m))  //合理排除被除数小于除数的情况
        {                                                    
              printf("0\n");

            for(i=lena;i>=0;i--)                                        
                if(a[i])
                break;                                                   //注意要输出商
                if(i==-1)
                printf("0");
                else
            for(;i>=0;i--)
            printf("%d",a[i]);
            printf("\n");
           continue;
        }
        else
        {
            for(i=lena-lenb;i>=0;i--)               //因为一开始除数后添加了 lena-lenb的0 所以之后需要一个一个消去添加的0
            {
                while(1)
                {
                    if(cp()==2)                   //检测除数是否小于被除数
                       break;
                       add(i);                     //除数后面添加了多少个0 就加上10的多少次方

                          for(z=0;z<lena;z++)       //减法部分
                      {
                             if(a[z]<b[z])
                         {
                             a[z]+=10;
                             a[z+1]--;
                         }
                             a[z]-=b[z];
                      }

                }
                 for(j=0;j<lena;j++)             //所有数向前移一位 相当于/10
                    b[j]=b[j+1];
            }
            for(i=lena;i>=0;i--)               //输出商
                if(s[i])
                break;
            for(;i>=0;i--)
            printf("%d",s[i]);
            printf("\n");

            for(i=lena;i>=0;i--)                //输出余数 注意余数为0也要输出
                if(a[i])
                break;
                if(i==-1)
                printf("0");
                else
            for(;i>=0;i--)
            printf("%d",a[i]);
            printf("\n");

        }
    }
    return 0;
}

写博客只为给自己的寒假训练一个交代 也证明一下自己还是有点东西的
欢迎和我交流QQ727518497!



猜你喜欢

转载自blog.csdn.net/ljq199926/article/details/79343823