Q:大整数的存储结构体该如何定义?
A:
struct bign {
int d[1000];
int len;
bign() {
memset(d, 0, sizeof(d));
len = 0;
}
}
注意:整数的高位存储在数组的高位,整数的低位存储在数组的低位。
如:23813存储为d[0]=3, d[1]=1, d[2]=8。。。
Q:如何把(数字)字符串读入成为大整数的结构体存储?
即实现函数bign change(char str[])
大整数结构体为:
struct bign {
int d[1000];
int len;
bign() {
memset(d, 0, sizeof(d));
len = 0;
}
}
A:
// 把整数转换为bign
bign change(char str[]) {
bign a;
a.len = strlen(str);
for (int i = 0; i < a.len; ++i) {
// 逆着赋值
a.d[i] = str[a.len - i - 1] - '0';
}
}
Q:如何比较两个大整数变量的大小?
大整数结构体为:
struct bign {
int d[1000];
int len;
bign() {
memset(d, 0, sizeof(d));
len = 0;
}
}
A:
比较规则:先判断两者的len大小,如果不相等,则以长的为大;如果相等,则从高位到低位进行比较,知道出现某一位不等,就可以判断两个数的大小。
// 比较a和b大小,a大、相等、a小分别返回1、0、-1
int compare(bign a, bign b) {
if (a.len > b.len) return 1; // a大
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; // 只要有一位a大,则a大
else if (a.d[i] < b.d[i]) return -1;
}
return 0; // 两数相等
}
}
Q:高精度加法的原理步骤?
将该位上的两个数字和进位相加,得到的结果取个位数作为该位结果,取十位数作为新的进位。
Q:高精度的加法实现的代码?
// 高精度a+b
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;
}
// 如果最后进位不为0,则直接赋给结果的最高位
if (carry != 0) {
c.d[c.len++] = carry;
}
return c;
}
Q:高精度减法的原理步骤?
对某一步,比较被减位和减位,如果不够减,则令被减位的高位减1、被减位加10再进行减法;如果够减,则直接减。最后一步要注意减法后高位可能有多余的0,要忽视它们,但也要保证结果至少有一位数。
Q:高精度减法的实现代码?
// 高精度a-b
bign sub(bign a, bign b) {
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) {
// 去除高位的0,同时至少保留一位最低位
--c.len;
}
return c;
}
使用sub函数前要比较两个数的大小,如果被减数小于减数,需要交换两个变量,然后输出负号,再使用sub函数。
Q:高精度与低精度的乘法的步骤原理?
取bign的某位与int型整体相乘,再与进位相加,所得结果的个位数作为该位结果,高位部分作为新的进位。
Q:高精度与低精度的乘法的实现代码?
// 高精度乘法
bign multi(bign a, int 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++] = temp % 10;
// 高位部分作为新的进位
carry = temp / 10;
}
// 和加法不一样,乘法的进位可能不止一位,因此用while
while (carry != 0) {
c.d[c.len++] = carry % 10;
carry /= 10;
}
return c;
}
Q:高精度与低精度的除法的步骤原理?
上一步的余数乘以10加上该步的位,得到该步临时的被除数,将其与被除数比较:
如果不够除,则该位的商为0;
如果够除,则商即为对应的商,余数即为对应的余数。
最后一步要注意减法后高位可能有多余的0,要忽视它们,但也要保证结果至少有一位数。
Q:高精度与低精度的除法的实现代码?
// 高精度除法,r为余数
bign divide(bign a, int b, int & r) {
bign c;
// 被除数的每一位和商的每一位是一一对应的,
// 因此先令长度相等
c.len = a.len;
// 从高位开始
for (int i = a.len - 1; i >= 0; --i) {
// 和上一位遗留的余数组合
r = r * 10 + a.d[i];
// 不够除,该位为0
if (r < b) c.d[i] = 0;
else { // 够除
c.d[i] = r / b; // 商
r = r % b; // 获得新的余数
}
}
while (c.len - 1 >= 1 && c.d[c.len - 1] == 0) {
// 去除高位的0,同时至少保留一位最低位
--c.len;
}
return c;
}