大整数运算

i n t : − 2 , 147 , 483 , 648 int:-2,147,483,648 int:2,147,483,648 ~ 2 , 147 , 483 , 647 2,147,483,647 2,147,483,647
大整数是超出基本数据类型表示范围的整数。

一、大整数的表示

定义一个结构体:

// 大整数用结构体表示
typedef struct tagBigInt
{
    int d[1000];
    int len;
}BigInt;

d的每一个元素都代表大整数的一位,len记录了大整数的长度。
在定义结构体变量后,需要初始化结构体:

// 大整数初始化
void initBigInt(BigInt *bign)
{
    memset(bign, 0, sizeof(bign->d));
    bign->len = 0;
}

输入的数字字符串中,字符串的低位是数字的高位。将其存入数组d中时,应将字符串逆序存放,使d数组中低位存放数字的低位:

// 将数字字符串转换成BigInt,数组低位存储低位数字
BigInt change(char *s)
{
    BigInt ret;
    ret.len = strlen(s);
    for(int i=0, j=ret.len-1; i<ret.len; i++, j--)
    {
        ret.d[i] = s[j] - '0';
    }
    return ret;
}

在显示时,将d数组从高位到低位依次输出:

// 输出BigInt,将数组逆序输出
void printBigInt(const BigInt *bign)
{
    for(int i=bign->len-1; i>=0; i--)
    {
        printf("%d", bign->d[i]);
    }
    printf("\n");
}

二、大整数的比较

先判断两者len的大小。如果不相等,则长的较大;如果相等,则从高位到低位依次比较每一位。

// 比较BigInt类型的大小
int compare(BigInt a, BigInt b)
{
    if(a.len > b.len)
    {
        return 1;
    }
    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;
            }
            else if(a.d[i] < b.d[i])
            {
                return -1;
            }
        }
        return 0;   // 相等
    }
}

三、大整数的四则运算

3.1 高精度加法

对其中一位进行加法的步骤:将该位上的两个数字与进位相加,得到的结果取个位作为该位的结果,取十位作新的进位。

// 高精度加法
BigInt add(BigInt a, BigInt b)
{
    BigInt ret;
    initBigInt(&ret);

    int carry = 0;  // 进位
    for( int i = 0; i < a.len || i < b.len; i++)    //以长的为界
    {
        int temp = a.d[i] + b.d[i] + carry; //对应位与进位相加
        ret.d[ret.len++] = temp % 10;     //取个位为该位结果
        carry = temp / 10;  //十位数作为新的进位
    }
    if(carry != 0)
    {
        ret.d[ret.len++] = carry;   //进位不为0,则赋给最高位
    }
    return ret;
}

3.2 高精度减法

对某一位:比较被减数和减数,若不够减,则向高位借位,即被减数的高位减1,被减数加10,再进行减法;如果够减,则直接减。

// 高精度减法
BigInt sub(BigInt a, BigInt b)
{
    BigInt ret;
    initBigInt(&ret);
    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
        }
        ret.d[ret.len++] = a.d[i] - b.d[i];//当前位结果
    }
    while( ret.len - 1 >= 1 && ret.d[ret.len-1] == 0)
    {
        ret.len--;//去除前导0,并保证结果至少有一位
    }
    return ret;
}

3.3 高精度与低精度的乘法

对某一位:将该位与int型整体相乘,再与进位相加,所得结果的个位作为该位结果,高位部分作为新的进位。


//高精度*低精度
BigInt multi(BigInt a, int b)
{
    BigInt ret;
    initBigInt(&ret);

    int carry = 0;  //进位
    for(int i=0; i<a.len; i++)
    {
        int temp = a.d[i] * b + carry;
        ret.d[ret.len++] = temp % 10;   //个位作为该位结果
        carry = temp / 10;

    }
    while( carry != 0)  //乘法的进位可能不止一位
    {
        ret.d[ret.len++] = carry % 10;
        carry /= 10;
    }
    return ret;
}

3.4 高精度除以低精度

对某一位:上一步的余数乘以10加上该位,得到该步临时的被除数,继续进行除法。


// 高精度除以低精度
BigInt divide(BigInt a, int b, int *r)
{
    BigInt ret;
    initBigInt(&ret);

    *r = 0;
    ret.len = a.len;    //被除数的每一位和商的每一位是一一对应的,先令长度相等
    for(int i=a.len-1; i>=0; i--)
    {
        *r = *r * 10 + a.d[i];
        if(*r < b)
        {
            ret.d[i] = 0;//不够除,该位商为0
        }
        else
        {
            ret.d[i] = *r / b;  //商
            *r = *r % b;  //新的余数
        }
    }
    while( ret.len - 1 >=1 && ret.d[ret.len-1] == 0)
    {
        ret.len--;  //去除前导0,并保证结果至少有一位
    }
    return ret;
}

总结:大整数的运算基本上就是模拟小学做算术的过程。
在传递结构体值的时候可以传地址,效率更高。

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值