大整数运算

Q:大整数的存储结构体该如何定义?
A:

struct bign {
    int d[1000];
    int len;
    bign() {
        memset(d, 0, sizeof(d));
        len = 0;
    }
}

注意:整数的高位存储在数组的高位,整数的低位存储在数组的低位。
如:23813存储为d[0]=3, d[1]=1, d[2]=8。。。

Q:如何把(数字)字符串读入成为大整数的结构体存储?
即实现函数bign change(char str[])
大整数结构体为:

struct bign {
    int d[1000];
    int len;
    bign() {
        memset(d, 0, sizeof(d));
        len = 0;
    }
}

A:

// 把整数转换为bign
bign change(char str[]) {
    bign a;
    a.len = strlen(str);
    for (int i = 0; i < a.len; ++i) {
        // 逆着赋值
        a.d[i] = str[a.len - i - 1] - '0';
    }
}

Q:如何比较两个大整数变量的大小?
大整数结构体为:

struct bign {
    int d[1000];
    int len;
    bign() {
        memset(d, 0, sizeof(d));
        len = 0;
    }
}

A:
比较规则:先判断两者的len大小,如果不相等,则以长的为大;如果相等,则从高位到低位进行比较,知道出现某一位不等,就可以判断两个数的大小。

// 比较a和b大小,a大、相等、a小分别返回1、0、-1
int compare(bign a, bign b) {
    if (a.len > b.len) return 1; // a大
    else if (a.len < b.len) return -1;
    else {
        for (int i = a.len - 1; i >= 0; --i) {
            if (a.d[i] > b.d[i]) return 1; // 只要有一位a大,则a大
            else if (a.d[i] < b.d[i]) return -1;
        }
        return 0; // 两数相等
    }
}

Q:高精度加法的原理步骤?
将该位上的两个数字和进位相加,得到的结果取个位数作为该位结果,取十位数作为新的进位。

Q:高精度的加法实现的代码?

// 高精度a+b
bign add(bign a, bign b) {
    bign c;
    int carry = 0; 
    // 以较长的为界限
    for (int i = 0; i < a.len || i < b.len; ++i) {
        // 两个对应位与进位相加
        int temp = a.d[i] + b.d[i] + carry;
        // 个位数为该位结果
        c.d[c.len++] = temp % 10;
        // 十位数为新的进位
        carry = temp / 10;
    }
    // 如果最后进位不为0,则直接赋给结果的最高位
    if (carry != 0) {
        c.d[c.len++] = carry;
    }
    return c;
}

Q:高精度减法的原理步骤?
对某一步,比较被减位和减位,如果不够减,则令被减位的高位减1、被减位加10再进行减法;如果够减,则直接减。最后一步要注意减法后高位可能有多余的0,要忽视它们,但也要保证结果至少有一位数。

Q:高精度减法的实现代码?

// 高精度a-b
bign sub(bign a, bign b) {
    bign c;
    // 以较长的为界限
    for (int i = 0; i < a.len || i < b.len; ++i) {
        if (a.d[i] < b.d[i]) { // 如果不够减
            --a.d[i+1]; // 向高位借位
            a.d[i] += 10; // 当前位加10
        }
        // 减法结果为当前位结果
        c.d[c.len++] = a.d[i] - b.d[i];
    }
    while (c.len - 1 >= 1 && c.d[c.len - 1] == 0) {
        // 去除高位的0,同时至少保留一位最低位
        --c.len;
    }
    return c;
}

使用sub函数前要比较两个数的大小,如果被减数小于减数,需要交换两个变量,然后输出负号,再使用sub函数。

Q:高精度与低精度的乘法的步骤原理?
取bign的某位与int型整体相乘,再与进位相加,所得结果的个位数作为该位结果,高位部分作为新的进位。

Q:高精度与低精度的乘法的实现代码?

// 高精度乘法
bign multi(bign a, int b) {
    bign c;
    int carry = 0; // 进位
    for (int i = 0; i < a.len; ++i) {
        int temp = a.d[i] * b + carry;
        // 个位作为该位结果
        c.d[c.len++] = temp % 10;
        // 高位部分作为新的进位
        carry = temp / 10;
    }
    // 和加法不一样,乘法的进位可能不止一位,因此用while
    while (carry != 0) {
        c.d[c.len++] = carry % 10;
        carry /= 10;
    }
    return c;
}

Q:高精度与低精度的除法的步骤原理?
上一步的余数乘以10加上该步的位,得到该步临时的被除数,将其与被除数比较:
如果不够除,则该位的商为0;
如果够除,则商即为对应的商,余数即为对应的余数。
最后一步要注意减法后高位可能有多余的0,要忽视它们,但也要保证结果至少有一位数。

Q:高精度与低精度的除法的实现代码?

// 高精度除法,r为余数
bign divide(bign a, int b, int & r) {
    bign c;
    // 被除数的每一位和商的每一位是一一对应的,
    // 因此先令长度相等
    c.len = a.len;
    // 从高位开始
    for (int i = a.len - 1; i >= 0; --i) {
        // 和上一位遗留的余数组合
        r = r * 10 + a.d[i];
        // 不够除,该位为0
        if (r < b) c.d[i] = 0;
        else { // 够除
            c.d[i] = r / b; // 商
            r = r % b; // 获得新的余数
        }
    }
    while (c.len - 1 >= 1 && c.d[c.len - 1] == 0) {
        // 去除高位的0,同时至少保留一位最低位
        --c.len;
    }
    return c;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值