大数类的简单实现

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

 

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

使用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.除法操作:

按照位运算来操纵。

 

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

以下是一个简单的 C++ 大数实现,它可以实现大数的加减运算: ``` #include <iostream> #include <string> #include <algorithm> using namespace std; class BigInt { public: string num; BigInt() {} BigInt(string s) { num = s; } BigInt operator+(BigInt b) { BigInt res; int carry = 0; int len1 = num.length(), len2 = b.num.length(); int len = max(len1, len2); for (int i = 0; i < len; i++) { int a = i < len1 ? num[len1 - 1 - i] - '0' : 0; int b = i < len2 ? b.num[len2 - 1 - i] - '0' : 0; int sum = a + b + carry; carry = sum / 10; sum = sum % 10; res.num.insert(0, to_string(sum)); } if (carry) { res.num.insert(0, to_string(carry)); } return res; } BigInt operator-(BigInt b) { BigInt res; int borrow = 0; int len1 = num.length(), len2 = b.num.length(); int len = max(len1, len2); for (int i = 0; i < len; i++) { int a = i < len1 ? num[len1 - 1 - i] - '0' : 0; int b = i < len2 ? b.num[len2 - 1 - i] - '0' : 0; int diff = a - b - borrow; if (diff < 0) { diff += 10; borrow = 1; } else { borrow = 0; } res.num.insert(0, to_string(diff)); } while (res.num.length() > 1 && res.num[0] == '0') { res.num.erase(0, 1); } return res; } void print() { cout << num << endl; } }; int main() { BigInt a("123456789"), b("987654321"); BigInt c = a + b; BigInt d = b - a; c.print(); // 输出 1111111110 d.print(); // 输出 864197532 return 0; } ``` 以上代码实现了 BigInt ,这个包含了 num 字符串,用来存储大数。它的构造函数可以接受一个字符串作为参数,用于初始化大数中的 `operator+` 和 `operator-` 分别实现大数的加法和减法。其中,加法的实现比较简单,使用了竖式加法的思想,从低位开始逐位相加,最后将结果逆序输出即可。减法的实现稍微复杂一些,需要考虑借位的情况。 最后,我们在 `main` 函数中创建了两个大数 a 和 b,分别进行了加法和减法运算,并将结果打印出来。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丈八涯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值