高精度除以低精度

以下这段代码的主要作用是将一个大整数(以字符数组形式表示)除以一个整数,并输出结果。具体来说,代码将大整数 a1(“1256”)除以整数 b(3),并输出商。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int main(){
    char a1[100]="1256";
    int a[100],c[100],lena,i,x=0,lenc,b=3;//a 用于存储被除数,c 用于存储商,x 用于保存进位,lenc 用于记录商的长度,b 是除数。
    //分别用于将数组 a 和 c 初始化为零。
    memset(a,0,sizeof(a));
    memset(c,0,sizeof(c));

    lena = strlen(a1);
    for(i=0;i<=lena-1;i++){//循环遍历被除数的字符,将其转换为整数并存储在数组 a 中。这是将字符数组形式的大整数转换为整数数组形式的关键步骤。
        a[i+1]=a1[i]-'0';
    }
    //遍历数组 a 中的每个数字,逐位执行除法操作,同时考虑上一位的余数 x。商被存储在数组 c 中,余数被保存在 x 中。
    for(i=1;i<=lena;i++){
        c[i]=(x*10+a[i])/b;//计算当前位置的值
        x=(x*10+a[i])%b;//取余,用于下一位的计算
    }
    lenc=1;//初始化商的长度。

    while(c[lenc]==0 && lenc<lena){//去除商中高位的零,同时更新商的长度 lenc。
        lenc++;
    }
    for(i=lenc;i<=lena;i++){
        cout<<c[i];
    }
    cout<<endl;
    return 0;
}

代码分析

  1. 大整数的表示和转换:首先,代码需要将字符数组 a1 中的大整数(“1256”)转换为整数数组 a 中。这是因为大整数通常会超出内置整数类型的范围,所以需要以数组形式表示。这部分的难点在于正确地将字符数字转换为整数,这里通过 '0' 字符的 ASCII 值来实现。
  2. 逐位除法操作:代码中使用两个循环来实现逐位的除法操作,从高位到低位。每一位的除法操作都需要考虑上一位的余数(x),并且在商 c 中存储本位的商。
  3. 进位处理:在除法操作中,余数可能需要被传递到下一位进行处理。这就是 x 变量的作用,用于存储和传递余数。
  4. 商的长度管理:代码需要正确地管理商的长度,以去除高位的零。这部分的难点在于确定商的实际长度,然后使用一个 while 循环来去除高位的零。

高精度除以高精度

在这种情况下,通常使用减法模拟来实现长除法。被除数的每一位都减去除数,一直减到当前位置的数字小于除数。然后,商的当前位增加1,然后继续减法操作。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int a[101],b[101],c[101],d,i;
void init(int a[],string s){
    a[0]=s.length();
    for(i=1;i<=a[0];i++){
        a[i]=s[a[0]-i]-'0';
    }
}
void print(int a[]){
    int i;
    if(a[0]==0 ){
        cout<<0<<endl;
        return;
    }
    for(i=a[0];i>0;i--){
        cout<<a[i];
    }
    cout<<endl;
    return;
}
int compare(int a[],int b[]){
    int i;
    if(a[0]>b[0]) {
        return 1;
    }
    if(a[0]<b[0]) {
        return -1;
    }
    for(i=a[0];i>0;i--){
        if(a[i]>b[i]) {
            return 1;
        }
        if(a[i]<b[i]) {
            return -1;
        }
    }
    return 0;
}
void jian(int a[],int b[]){
    int flag,i;
    flag=compare(a,b);
    if(flag==0){
        a[0]=0;
        return;
    }
    if(flag==1){
        for(i=1;i<=a[0];i++) {
            if (a[i] < b[i]) {
                a[i + 1]--;
                a[i]+=10;
            }
            a[i] -= b[i];
        }
        while(a[0]>0 && a[a[0]]==0){
            a[0]--;
        }
        return;
    }
}
void numcpy(int p[],int q[],int det){
    for (int i=1;i<=p[0];i++){
        q[i+det-1]=p[i];
    }
    q[0]=p[0]+det-1;
}

void chugao(int a[],int b[],int c[]){
    int i,tmp[101];
    c[0]=a[0]-b[0]+1; // 设置商的长度,初始为被除数长度减去除数长度加1
    for(i=c[0];i>0;i--){
        memset(tmp,0,sizeof(tmp));
        numcpy(b,tmp,i);// 复制除数 b 到 tmp 数组,同时指定偏移量 i
        while(compare(a,tmp)>=0) {
            c[i]++;
            jian(a, tmp);
        }
    }
    while(c[0]>0 && c[c[0]]==0){
        c[0]--;
    }
    return;
}

int main(){
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(b));
    memset(c,0,sizeof(c));
    init(a,"1000");
    init(b,"3");
    chugao(a,b,c);
    print(c);
    print(a);
    return 0;
}

代码分析

这段代码是一个C++程序,它执行了大整数的除法操作。具体来说,它实现了两个大整数(可以超过标准整数范围)的相除,并输出结果。

chugao 函数的目的是执行大整数的除法操作,它使用循环来模拟手工的长除法过程,得到商(c 数组)和余数(a 数组)。

下面是 chugao 函数的详细分析:

void chugao(int a[], int b[], int c[]) {
    int i, tmp[101];
    c[0] = a[0] - b[0] + 1; // 设置商的长度,初始为被除数长度减去除数长度加1
    for (i = c[0]; i > 0; i--) {
        memset(tmp, 0, sizeof(tmp)); // 清空 tmp 数组
        numcpy(b, tmp, i); // 复制除数 b 到 tmp 数组,同时指定偏移量 i
        while (compare(a, tmp) >= 0) {
            c[i]++; // 假设商的当前位为 1
            jian(a, tmp); // 从被除数 a 中减去 tmp(相当于减去除数 b)
        }
    }
    while (c[0] > 0 && c[c[0]] == 0) {
        c[0]--; // 去除商中的前导零
    }
    return;
}

详细步骤:

  1. 首先,函数会计算商 c 的长度,由 c[0] 表示,计算方式是被除数 a 的长度减去除数 b 的长度,再加1。这是因为商的位数可能比这个计算结果多一位,以容纳小数部分。
  2. 然后,使用 for 循环从商的最高位向最低位处理每一位。
  3. 在每次循环迭代中,首先清空 tmp 数组,用 memset 函数将其所有元素初始化为 0。tmp 数组用于存储除数 b,并且会在不断的迭代中右移,模拟手工长除法的过程。
  4. 使用 numcpy 函数将除数 b 复制到 tmp 数组中,并指定偏移量 i。这相当于将 b 放在正确的位置,以便与被除数 a 进行比较和减法操作。
  5. 进入内部循环,该循环会一直执行,直到无法再减去 tmp 为止。在每次迭代中,假设商 c 的当前位为1,然后从被除数 a 中减去 tmp。这模拟了手工长除法中的减法步骤。
  6. 最后,退出内部循环后,通过检查商 c 的最高位是否为0来去除可能存在的前导零。