每日一练——大数加减乘除运算实现(网易笔试题)

前几天做网易笔试题时最后一道题是设计一个大数类,实现加减运算,因为做这道题时只有5分钟,结果我刚把类写出来,考试时间就结束了。其实在去年12月我写过一个RSA的加解密程序,其中就用到了大数的加减乘除运算(当然这只是RSA用到的一小部分),没有把最后一题写上去实在太可惜了(>﹏<。)~,今天把我设计的大数类贴出来,后面顺便附上面试时经常会让手写的加、减、乘代码。

一般的,我们会用一个很大的数组来表示一个大数,数组中的每一个数(0~9)来代表大数中的某一位,比如big_num[1000],那么这个数能够表示1000位大数,后来又人想到用数组中的每个数来表示0~99999999,这样数组只需要1000 / 8 = 125个元素即可实现。那么问题来了,一个unsigned long能表示的范围是0~4294967295也就是十六进制的0~0xFFFFFFFF,为什么我们不充分利用unsigned long能表示范围的的每一个数呢?

#define MAXLEN 64
typedef unsigned char BYTE; 

class big_int
{
public:
    ......
    void set_zero();//大数清零
    void modify_bit();//修正大数位数
    big_int& mov(big_int &obj);//大数赋值大数
    int cmp(big_int &obj);//两个大数进行比较,大于返回1,等于返回0,小于返回-1
    big_int& add(big_int &num1, big_int &num2);//大数加大数 A=B+C
    big_int& add(big_int &num);//大数加大数 A+=B
    big_int& Sub(big_int &num1, big_int &num2);//大数减大数 A=B-C
    big_int& Sub(big_int &num);//大数减大数 A-=B
    big_int& mul(big_int &num1, big_int &num2);//大数乘大数 A=B*C
    big_int& mul(big_int &num);//大数乘大数 A*=B
    big_int& div(big_int &num1, big_int &num2);//大数除大数 A=B/C
    big_int& div(big_int &num);//大数除大数 A/=B
    ......            
public:
    int sign;//正数为1,负数为0
    uint32_t data[MAXLEN];//数组中每一个数代表大数2^32次方进制的每一位
    int length;//大数使用int的长度
    int bit;//大数的二进制位位数
};


//大数加大数A=B+C
big_int& big_int::add(big_int &num1, big_int &num2)
{
    uint32_t carry = 0;
    uint64_t tmp;//用于存放两个无符号整形数(32位)的和,结果可能超过32位

    set_zero();

    length = num1.length > num2.length ? num1.length : num2.length;

    for (int i = 0; i < length; i++)
    {
        tmp = (uint64_t)num1.data[i] + (uint64_t)num2.data[i] + (uint64_t)carry;
        data[i] = (uint32_t)(tmp & 0x00000000FFFFFFFF);//data[i] = tmp % 0x100000000
        carry = (uint32_t)(tmp >> 32);//carry = tmp / 0x100000000)
    }

    if 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值