大整数运算

2020-02-13  本文已影响0人  km15

一、定义、赋值、比较、输出
1、大整数的结构体

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

2、逆着赋值(先用字符串读入,再把字符串另存值bign结构体)
思想:1、生成结构体 2、赋值len 3、for逆着赋值

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';
    }

    return a;
}

3、比较两个bign变量大小
思想:1、先比较长度,长度不同则以长的为大 2、长度相同,则从高到低比较

int compare(bign a, bign b) {
    if (a.len > b.len)  return 1;   //a大
    else if (a.len < b.len) return -1;  //b大
    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;    //只要有一位b大,则b大
        }
        return 0;       //两数相等
    }
}

二、四则运算(高精度加法,高精度减法,高精度与低精度乘法,高精度与低精度除法)
1、加法
思想:其中一位加法,改为上的两个数字和进位相加,得到的结果个位数作为该位的结果,取十位数作为进位

bign add(bign a, bign b) {
    bign c;
    int carry = 0;  //carry是进位
    for (int i = 0;i < a.len || i < b.len;++i) {    //以较长为界限
        int temp = a.d[i] + b.d[i] + carry; //两个对应为与进位相加
        c.d[len++] = temp % 10; //个位数为结果
        carry = temp / 10;  //十位数位进位
    }
    if (carry != 0) {
        c.d[len++] = carry;
    }
    return c;
}

注意:
(1)以上写法都是非负整数
(2)如果有一方式负数,可以再转换数组这一步去掉其负号,然后采用高精度减法
(3)如果两个都是负数,就都去掉负号,然后高精度加法,最后再加上负号

2、减法
思想:对某一步,比较被减位和减位,如果不够减,则令被减位的高位减1,被减位加10再进行减法;
如果够减,则直接减。
最后一步要注意减法后高位可能有多余的0,要五十他们,但也要保证结果至少有一位数

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

注意:
1、使用sub函数需要比较两个数大小,如果被减数小于减数,
交换两个变量
输出符号
再使用sub函数

3、高精度与低精度乘法
思想:去bign某位与Int整体相乘,再与进位相加,所得结果的个位数作为该位结果,高位部分作为新的进位

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

注意:
如果a和b中存在负数,需要先记录负号,然后取绝对值进入函数

4、高精度与低精度除法
算法思想:
1、得出某一步的步骤:上一步的余数乘以10加上该步的位,得到该步临时的被除数,
2、将其与除数比较,如果不够除,则该位的商为0,如果够除,则商为对应的商,余数为对应的余数
3、最后一步要注意减法后高位可能有多余的0,要忽视他们,但也要保证结果至少有一位

bign divide(bign a, bign b,int & r) {   //高精度除法,r为余数
    bign c;
    c.len = a.len;  //被除数的每一位和商的每一位是一一对应的,因此先令长度相等
    for (int i a.len - 1;i >= 0;--i) {
        r = r * 10 + a.d[i];
        if (r < b) c.d[i] = 0;  //不够除
        else{   //够除
            c.d[i] = r / b; //商
            r = r % b;  //获得新的余数
        }
    }

    while (c.len - 1 >= 1 && c.d[len - 1] == 0) {
        c.len--;    //取出高位的0,同时至少保留一位最低位
    }
    return c;
}

注意:
1、很多题目要求得出商和余数,但只能返回一个值,所以把余数作为引用,或者作为全局变量

上一篇 下一篇

猜你喜欢

热点阅读