大整数的四则运算

之前写过一套“大实数”的算法,但那一套采用的是C++、只有加法与乘法、注释残缺不全(Δεν ξέρω καν τι γράφω)。还是以一种负责的态度将源码重置一下吧。

前作:用线性顺序表(数组)计算大实数加法与大实数乘法

#include <stdlib.h>
#include <string.h>

// 设置大整数精度
#define PRECISION (25)

// 自定义类型
typedef struct {
    int valueArray[PRECISION];
} BigInteger;
typedef char* String;

// 输入数值
BigInteger setValue(String _string) {
    // 初始化大整数结构体实例,所有位被初始化为0
    BigInteger temp;
    memset(&temp, 0, sizeof(BigInteger));
    // 获取大整数字符串的长度
    int length = strlen(_string);
    for (int i = length - 1, j = PRECISION - 1; i >= 0; i--, j--) {
        // 从右向左提取字符串的每一位数字,存入大整数数组中
        temp.valueArray[j] = (int)(_string[i] - '0');
    }
    return temp;
}

// 读取数值
String getValue(BigInteger _bigInteger) {
    // 获取大整数长度
    int length = 25;
    for (; _bigInteger.valueArray[25 - length] == 0; length--) { }
    if (length == 0) {
        length = 1;
    }

    char* string = (char*)calloc(length + 1, sizeof(char));
    string[length] = '\0';
    for (int i = 0; i < length; i++) {
        // 从左到右将大整数数组的每一位转化为字符
        string[i] = (char)(_bigInteger.valueArray[25 - length + i] + '0');
    }
    return string;
}

// 大整数加法
BigInteger add(BigInteger _param1, BigInteger _param2) {
    // 新建空结果
    BigInteger result = setValue("0");
    // 进位标记
    int extra = 0;
    // 加法运算从低位(右)向高位(左)进行
    for (int i = PRECISION - 1; i >= 0; i--) {
        int sum = _param1.valueArray[i] + _param2.valueArray[i] + extra;
        result.valueArray[i] = sum % 10;
        extra = sum / 10;
    }
    return result;
}

// 大整数减法
BigInteger minus(BigInteger _param1, BigInteger _param2) {
    // 新建空结果
    BigInteger result = setValue("0");
    // 借位标记
    int borrow = 0;
    // 减法运算从低位(右)向高位(左)进行
    for (int i = PRECISION - 1; i >= 0; i--) {
        // 若被减数小于减数,则需要借位
        if (_param1.valueArray[i] < _param2.valueArray[i]) {
            result.valueArray[i] = 10 + _param1.valueArray[i] - _param2.valueArray[i] - borrow;
            borrow = 1;
        }
        // 否则直接相减
        else {
            result.valueArray[i] = _param1.valueArray[i] - _param2.valueArray[i] - borrow;
            borrow = 0;
        }
    }
    return result;
}

// 大整数乘法
BigInteger multipy(BigInteger _param1, BigInteger _param2) {
    // 新建空结果
    // 由于乘法会导致数位快速增长,所以另外新建结果数组,清算后再截取
    int temp[2 * PRECISION] = { 0 };
    // 笛卡尔乘法,模拟竖式运算
    // 第1步,乘数按位进行分配,得到各位的结果
    for (int i = PRECISION - 1; i >= 0; i--) {
        for (int j = PRECISION - 1; j >= 0; j--) {
            // ★难点:此处需要通过下标对结果进行数位对齐
            temp[i + j + 1] = temp[i + j + 1] + _param1.valueArray[j] * _param2.valueArray[i];
        }
    }
    // 第2步,清算分配结果和进位
    int extra = 0, sum = 0;
    for (int i = 2 * PRECISION - 1; i >= 0; i--) {
        sum = temp[i] + extra;
        temp[i] = sum % 10;
        extra = sum / 10;
    }
    // 新建空白结果
    BigInteger result = setValue("0");
    // 忽略真实结果左侧超出精度的值
    for (int i = 0; i < PRECISION; i++) {
        result.valueArray[PRECISION - i - 1] = temp[2 * PRECISION - i - 1];
    }
    return result;
}

// 大整数比较
int compare(BigInteger _param1, BigInteger _param2) {
    // 从高位(左)向低位(右),逐位比对
    for (int i = 0; i < 25; i++) {
        // 小于为-1
        if (_param1.valueArray[i] < _param2.valueArray[i]) {
            return -1;
        }
        // 大于为1
        else if (_param1.valueArray[i] > _param2.valueArray[i]) {
            return 1;
        }
    }
    // 完全相同则为0
    return 0;
}

// 大整数除法
BigInteger divide(BigInteger _param1, BigInteger _param2) {
    // 被除数小于除数,返回 0
    if (compare(_param1, _param2) == -1) {
        return (BigInteger) { { 0 } };
    }

    // 记录两个大整数的长度
    int numberLength[2] = { 25, 25 };
    while (_param1.valueArray[25 - numberLength[0]] == 0) {
        numberLength[0] -= 1;
    }
    while (_param2.valueArray[25 - numberLength[1]] == 0) {
        numberLength[1] -= 1;
    }
    // 两个整数的长度差
    int expotential = numberLength[0] - numberLength[1];
    // 结果寄存器
    BigInteger result = setValue("0");
    // 除数放大
    for (int i = numberLength[1]; i >= 1; i--) {
        _param2.valueArray[25 - i - expotential] = _param2.valueArray[25 - i];
    }
    for (int i = 1; i <= expotential; i++) {
        _param2.valueArray[25 - i] = 0;
    }

    // 迭代减法
    while (expotential >= 0) {
        while (compare(_param1, _param2) >= 0) {
            _param1 = minus(_param1, _param2);
            result.valueArray[24 - expotential] += 1;
        }
        expotential -= 1;
        // 除数缩小
        for (int i = 24 - expotential; i >= 1; i--) {
            _param2.valueArray[i] = _param2.valueArray[i - 1];
            _param2.valueArray[0] = 0;
        }
    }

    return result;
}

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

️是纱雾酱哟~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值