#C08L03P01. C08.L03.高精度除法.概述

C08.L03.高精度除法.概述

在读小学时,我们做除法都采用竖式方法计算。被除数从高位开始,和除数对齐,逐位“试商”,“试商”后除数减去“试商”的数的乘积,如下图所示。

img

采用计算机做高精度除法时,模拟日常除法的步骤。但计算机不可能做“试商”,这时,我们可以采用减法来模拟。

试商过程

  1. 将除数移动和被除数对齐,位数不够时,补 0。

  2. 利用被除数减去除数,一直减到被除数小于除数,减的次数,就是“试商”的结果,每移动一次。

  3. 重复上述步骤,一直到被除数和除数的位数相等为止。

举例说明

举一个例子,比如 524134 除以 123,结果是 4261 ,余数为 31。

  1. 第一位 4 的来源是我们把 524 和 123 对齐,然后进行循环减法,循环了 4 次,余 32;

  2. 将 32134 的前三位 321 继续和 123 对齐,循环减法 2 次,余 75;

  3. 把 7534 的前三位 753 和 123 对齐,循环减法 6 次,余 15;

  4. 将 154 和 123 对齐,只能减 1 次,余 31。

所以 524134 除以 123,结果是 4261,余数为 31。

计算过程

img

高精度除法实现

设计思路:

  1. 定义存储数组。

  2. 读入数据处理。

  3. 试商过程。

  4. 删除前导 0 。所谓前导零,就是出现类似这样数据 01234,这个 0 实际是不需要的。

  5. 输出结果。倒序输出减法的结果数组 C,因为我们的个位是存储在下标为 0 的地方。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 300+4; //根据题目的最大值。+4为了防止A+B出现进位
string s1;//存储字符串
string s2;//存储字符串
int tmp[MAXN] = {};//交换用字符串
int a[MAXN] = {};//存储加数A
int b[MAXN] = {};//存储加数B
int c[MAXN] = {};//存储和B
int compare(int a[], int b[]) {
    //索引为0的数据为数组长度
    if (a[0]>b[0])
        return 1;
    else if (a[0]<b[0])
        return -1;

    //逐位比较
    for (int i=a[0]; i>0; i--) {
		if (a[i]>b[i])
			return 1;
		else if (a[i]<b[i])
			return -1;
    }

    return 0;
}

void numcpy(int a[],int b[],int dest) {
    //将数组右移,使两个数组右端对齐,形参q数组储存右移后的结果
    for (int i=1;i<=a[0];i++) {
        b[i+dest-1] =a[i];
    }
    b[0] = a[0]+dest-1;
}

int main() {

    cin>>s1>>s2;//读入字符串

    //处理负数
    bool flaga = false;//乘数a的符号
    if ('-'==s1[0]) {
		flaga = true;
		s1.erase(s1.begin());;//删除负号
    }

    bool flagb = false;//乘数b的符号
    if ('-'==s2[0]) {
		flagb = true;
		s2.erase(s2.begin());;//删除负号
    }

    //处理输出的负号
    if (flaga!=flagb)
        printf("-");//商为负数


    //处理乘数1
    int len = s1.size();
    a[0] = len;
    for (int i=0; i<len; i++)
		a[len-i]=s1[i]-'0';

    //处理乘数2
    len = s2.size();
    b[0] = len;
    for (int i=0; i<len; i++)
		b[len-i]=s2[i]-'0';

    if (0==compare(a,b)) {
        //两数相等
        printf("1\n0\n");
        return 0;
    }
	else if (compare(a,b)==-1){
		//被除数小,除数大
		printf("0\n");//输出除数
		if (true==flaga) {
		    printf("-");
		}
		cout<<s1<<endl;
		return 0;
    }
	else {
        c[0] = a[0]-b[0]+1;
        for (int i=c[0]; i>0; i--) {
            memset(tmp, 0, sizeof(tmp));
            //高位对齐
            numcpy(b,tmp,i);

            while (compare(a, tmp)>=0) {
                c[i]++;
                //减法
                for (int j=1; j<=a[0]; j++) {
                    if (a[j]<tmp[j]) {
                        a[j+1]--;
                        a[j]+=10;
                    }
                    a[j]-=tmp[j];
                }

                int k=a[0];
                while (a[k]==0)
                    k--;

                a[0]=k;
            }
        }

        //控制最高位的0
        while (c[0]>0 && c[c[0]]==0)
            c[0]--;

    }

    //逆序打印输出商和余数
    for (int i=c[0]; i>0; i--)
        printf("%d", c[i]);

    printf("\n");

    if (0==a[0])
        printf("0\n");

	else
	{
		if (true==flaga)
			printf("-");

        for (int i=a[0]; i>0; i--)
            printf("%d", a[i]);

        printf("\n");
    }
    return 0;

}