C 语言实现大整数运算:二进制字符数组表示法

为了解决大整数的表示与运算溢出问题,可以使用二进制字符数组表示法。将大整数先转换成二进制,再把二进制中的每一位,0 或 1,以'0' 或 '1' 字符的形式,从低到高位依次存放到一个字符数组中,称为大数的二进制字符数组表示。本文将使用这种方法实现 2 个大整数的加减乘除等基本运算。

注意: 以下代码实现中,为了方便起见,采用了将字符数组中的每个字符转换成整型数的方式进行运算。实际上,如果需要更高的效率,可以采用类似于手算加减乘除的方式进行运算,不用将字符数组中的每个字符转换成整型数。

加法运算:

#include <stdio.h>
#include <string.h>

#define MAX_LEN 1000 // 定义最大字符数组长度

void add(char a[], char b[], char sum[]) {
    int i, j, k;
    int carry = 0; // 进位
    int len_a = strlen(a);
    int len_b = strlen(b);

    for (i = len_a - 1, j = len_b - 1, k = 0; i >= 0 || j >= 0 || carry; i--, j--, k++) {
        int x = (i >= 0 ? a[i] - '0' : 0); // 取出 a 数组当前位的数值,如果已经到了最高位,则用 0 补充
        int y = (j >= 0 ? b[j] - '0' : 0); // 取出 b 数组当前位的数值,如果已经到了最高位,则用 0 补充
        int z = x + y + carry; // 计算当前位的数值
        sum[k] = z % 10 + '0'; // 将当前位的数值存储到 sum 数组对应位置
        carry = z / 10; // 计算进位
    }

    sum[k] = '\0'; // 将 sum 数组最后一位赋为 '\0',表示字符串结束
    strrev(sum); // 反转 sum 数组,使得最高位在前,最低位在后
}

减法运算:

#include <stdio.h>
#include <string.h>

#define MAX_LEN 1000 // 定义最大字符数组长度

void subtract(char a[], char b[], char diff[]) {
    int i, j, k;
    int borrow = 0; // 借位
    int len_a = strlen(a);
    int len_b = strlen(b);

    for (i = len_a - 1, j = len_b - 1, k = 0; i >= 0 || j >= 0; i--, j--, k++) {
        int x = (i >= 0 ? a[i] - '0' : 0); // 取出 a 数组当前位的数值,如果已经到了最高位,则用 0 补充
        int y = (j >= 0 ? b[j] - '0' : 0); // 取出 b 数组当前位的数值,如果已经到了最高位,则用 0 补充
        int z = x - y - borrow; // 计算当前位的数值
        if (z < 0) {
            z += 10; // 如果需要借位,则将当前位加上 10
            borrow = 1; // 设置借位标志
        } else {
            borrow = 0; // 清除借位标志
        }
        diff[k] = z + '0'; // 将当前位的数值存储到 diff 数组对应位置
    }

    while (k > 1 && diff[k - 1] == '0') k--; // 去掉 diff 数组中的前导零
    diff[k] = '\0'; // 将 diff 数组最后一位赋为 '\0',表示字符串结束
    strrev(diff); // 反转 diff 数组,使得最高位在前,最低位在后
}

乘法运算:

#include <stdio.h>
#include <string.h>

#define MAX_LEN 1000 // 定义最大字符数组长度

void multiply(char a[], char b[], char product[]) {
    int i, j, k;
    int len_a = strlen(a);
    int len_b = strlen(b);
    int len_product = len_a + len_b; // 计算乘积的最大长度
    int carry;

    memset(product, '0', len_product); // 将 product 数组初始化为 '0'

    for (i = len_a - 1; i >= 0; i--) {
        carry = 0; // 初始化进位
        for (j = len_b - 1; j >= 0; j--) {
            int x = a[i] - '0'; // 取出 a 数组当前位的数值
            int y = b[j] - '0'; // 取出 b 数组当前位的数值
            int z = x * y + carry + product[i + j + 1] - '0'; // 计算当前位的乘积
            carry = z / 10; // 计算进位
            product[i + j + 1] = z % 10 + '0'; // 将当前位的数值存储到 product 数组对应位置
        }
        product[i + j + 1] = carry + '0'; // 将进位存储到 product 数组对应位置
    }

    while (*product == '0' && *(product + 1) != '\0') product++; // 去掉 product 数组中的前导零
}

除法运算:

#include <stdio.h>
#include <string.h>

#define MAX_LEN 1000 // 定义最大字符数组长度

void divide(char a[], char b[], char quotient[], char remainder[]) {
    int i, j, k;
    int len_a = strlen(a);
    int len_b = strlen(b);
    int len_quotient = len_a - len_b + 1;
    int len_remainder = len_b;
    int temp[MAX_LEN];
    int q, r; // 商和余数的当前位
    int carry;

    if (len_a < len_b) { // 如果被除数小于除数,直接将被除数赋值给余数,商为 0
        strcpy(remainder, a);
        quotient[0] = '0';
        quotient[1] = '\0';
        return;
    }

    for (i = len_a - 1; i >= 0; i--) {
        memset(temp, 0, sizeof(temp)); // 将 temp 数组初始化为 0
        carry = 0; // 初始化进位
        for (j = len_b - 1, k = len_b - 1; j >= 0; j--, k--) {
            int x = a[i] - '0'; // 取出 a 数组当前位的数值
            int y = b[j] - '0'; // 取出 b 数组当前位的数值
            int z = x * y + carry; // 计算当前位的乘积
            carry = z / 10; // 计算进位
            temp[k] = z % 10; // 将当前位的数值存储到 temp 数组对应位置
        }
        temp[k] = carry; // 将进位存储到 temp 数组对应位置

        q = 0; // 初始化商的当前位
        while (q < 10 && compare(temp, b, len_b) >= 0) { // 如果 temp 大于等于 b,则进行除法运算
            subtract(temp, b, temp);
            q++;
        }

        quotient[i - len_b + 1] = q + '0'; // 将商的当前位存储到 quotient 数组对应位置

        if (i >= len_b) {
            carry = a[i - len_b] - '0'; // 取出 a 数组当前位的数值
            for (j = len_b - 1; j >= 0; j--) {
                temp[j + 1] = temp[j]; // 将 temp 数组向左移动一位
            }
            temp[0] = carry; // 将 a 数组当前位存储到 temp 数组对应位置
        }
    }

    while (*quotient == '0' && *(quotient + 1) != '\0') quotient++; // 去掉 quotient 数组中的前导零
    strcpy(remainder, temp); // 将 temp 数组赋值给余数
}

比较两个整数的大小:

#include <string.h>

#define MAX_LEN 1000 // 定义最大字符数组长度

int compare(int a[], int b[], int len) {
    int i;
    for (i = 0; i < len; i++) {
        if (a[i] != b[i]) {
            return (a[i] > b[i]) ? 1 : -1;
        }
    }
    return 0;
}
C 语言实现大整数运算:二进制字符数组表示法

原文地址: https://www.cveoy.top/t/topic/nJ6w 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录