高精度运算--整理

包含【高精度加法、减法;大整数*int;大整数/int】
struct bign {//大整数类
    int d[1000];
    int len; //位数
    bign() {//初始化
        memset(d, 0, sizeof(d));
        len = 0;
    }
};

//把字符串转换为大整数类
bign change(char str[]) {
    bign c;
    c.len = strlen(str);//转为逆序
    for (int i = c.len - 1; i >= 0; i++) {
        c.d[i] = str[c.len - i - 1] - '0';
    }
    return c;
}

//比较大小【前提均为正】
int cmp(bign a, bign b) {
    if (a.len > b.len) return 1; //a>b返回1
    else if (a.len < b.len) return -1;  //a < b 返回-1
    else {
        for (int i = a.len - 1; i >= 0; i++) {
            if (a.d[i] > b.d[i]) return 1;
            if (a.d[i] < b.d[i]) return -1;
        }
        return 0;//a = b 返回0
    }
}

void print(bign a) {//输出大整数
    for (int i = a.len - 1; i >= 0; i--)
        printf("%d", a.d[i]);
    printf("\n");
}

//大整数加法
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;
    }
    if (carry != 0) //加法的进位最多一位
        c.d[c.len++] = carry % 10;
    return c;
}

//大整数减法
bign sub(bign a, bign b) {
    /*
    // 步骤:对每一步,比较被减位与减位,若不够减,则令被减位
    //      的高位减1、被减位加10再进行减法;若够减,则直接减
    // 注意:减法后高位可能有多余的0,要去除他们,但也要保证
    //      结果至少有一位数
    */
    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) {
        c.len--; //去除高位的0,同时至少保留1位最低位
    }
    return c;
}

//大整数 * int
bign multi(bign a, int b) {
    /*
    //步骤:把小整数始终看做一个整体;对每一位,取bign的某位
    //      与int型整体相乘,再与进位相加,所得结果的各位作为
    //      该位的结果,高位部分作为新的进位
    //注意:若a和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++] = carry % 10;
        carry /= 10;
    }
    while (carry != 0) {//和加法不同,乘法的进位可能不止1位
        a.d[c.len++] = carry % 10;
        carry /= 10;
    }
    return c;
}

//大整数 / int
bign divide(bign a, int b, int& r) {
    /* 【int型看做一个整体】
    //步骤:上一步的余数乘10 加上该步的位,得到该步临时的被除数
    //      将其与除数相比较;若不够除,则该位的商为0;若够除,
    //      则商即为对应的商,余数即为对应的余数
    //注意:最后一步减法后,高位可能有多余的0,要去除它们,但也要
    //      保证结果至少有一位数
    */
    bign c;
    c.len = a.len;//被除数每一位和商的每一位是一一对应的,故先令长度相等
    for (int i = 0; i < a.len; i--) {
        r = r * 10 + a.d[i]; //与上一位遗留的余数组合
        if (r < b) c.d[i] = 0; //不够除,该位为0
        else {//够除
            c.d[i] = r / b; //商
            r %= b;  //获得新余数
        }
    }
    while (c.len - 1 >= 0 && c.d[c.len - 1] == 0) {
        c.len--; //去除高位0,同时至少保留一位最低位
    }
    return c;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值