大数类的简单实现

来源:互联网 发布:电脑网络电话软件 编辑:程序博客网 时间:2024/06/06 05:03

本文仅做参考,主要是体现大数实现原理。

 

大数操作是使用计算机计算经常遇到的问题。

使用VS2005,在32位的机器上

 

各个类型的大小:

sizeof(int): 4

sizeof(unsigned): 4

sizeof(long): 4

sizeof(long long): 8

sizeof(char): 1

 

因此,unsigned的二进制位数为:4*8=32位,能够表示的最大数为:4294967295

11111111 11111111 11111111 11111111

而 long long 最大能够表示的无符号数为2^64 -1=18446744073709551615

因此,实现一个大数类是很有必要的。

网上有很多以实现不错的大数类,我这里只是练习练习。

 

使用数组记录大数据:

 

 * 这里列举vector<char> dats表示大数

 *100000的二进制为:
 * 1111 01000010 01000000
 *将之存放到数组中为:
 * -----------------     -----------------        -----------------
 * |   第2个元素   |   |   第1个元素   |       |   第0个元素   |
 * -----------------     -----------------        -----------------
 * | | | | |1|1|1|1| | |1|0|0|0|0|1|0| | |1|0|0|0|0|0|0|
 * ----------------- ----------------- -----------------
 * 即:dats[0] = 64,dats[1] =66,dats[2]=15
 * 还原方法:((dats[2]*2^8)+dats[1])*2^8+dats[0] = 100000

 

 

定义一个大数类的结构:

class bigint 

{ 

    char sign;      //符号0:+, 1:-                   

    vector<unsigned> dats;

}

 

1.string转到dats,可以通过用2除来转为二进制。

例如:string numStr = 76543210;

首先由于末位为0,为偶数,所以记录0,结果为0

7&1==1 有补位给6, 7>>1 = 3

16&1==0 无补位, 16>>1 = 8

5&1 ==1 有补位给4 5>>1 = 2

14&1 ==0 无补位

 

最后得到38271605

由于末位为5,为奇数,所以再记录1,结果为10

在次除2得到19135802

由于末位为2,为偶数,所以再记录0,结果为010

.

最后当末位为1,为奇数,再记录1,结果为100100011111111010011101010

 

当然也可以采用分块计算,即把numStr分成多个整数,如:

numStr = 755432109876543210;

可以每次取8位放入到vector<unsigned> arr中,得到:

Arr = {75,54321098,76543210};

同样,也可以按照上面的除法,只是数组元素之间的补位值相当于10^8

如,第一个数75&1==1,所以补位为1,也就说,

下一个数是154321098>>1.

 

 

2.加操作:

对应dats各块,进行加,数组的每个位置和用long long carry记录,则该为的值 = carry & (1<<32 -1)

而进位值为carry>>32.具体需要注意位对齐细节,以及最后的进位处理,可能会进位多次。还要注意数的符号。

 

3.减操作:

减法是通过反码来实现的,其实就是利用越界来实现。

如:正数A 正数B,首先求正数B的反码

若当相减之后为正数,那就是(正数A + 正数B的反码)再加1.

若相减之后为负数,那么就是(正数A + 正数B的反码)再取反码。当然别忘了修改符号sign

 

对于乘除,则需要对数组各个部分进行分开来看,考虑进位即可。

跟加法很相似,只是原来各位置相加变为一个位置对应多个位置的相加。

 

4.除法操作:

按照位运算来操纵。

 

贴上代码,代码只是半成品,未经过测试,不能直接使用。