C语言实现大整数加减乘除运算:二进制字符数组存储
首先,需要定义一个结构体来表示大整数:
#define MAX_LEN 1000 // 大整数最大长度
struct BigInt {
int len; // 大整数的长度
char digits[MAX_LEN]; // 大整数的每一位,存放在字符数组中
};
接下来,实现大整数的加减乘除运算。
加法
大整数的加法可以看成是两个二进制数的加法,只需要从右往左逐位相加,记得处理进位即可。
// 大整数加法
struct BigInt add(struct BigInt a, struct BigInt b) {
struct BigInt c = {0};
int carry = 0; // 进位
int i, j;
for (i = a.len - 1, j = b.len - 1; i >= 0 || j >= 0; i--, j--) {
int x = i >= 0 ? a.digits[i] - '0' : 0;
int y = j >= 0 ? b.digits[j] - '0' : 0;
int sum = x + y + carry;
c.digits[c.len++] = sum % 2 + '0';
carry = sum / 2;
}
if (carry) {
c.digits[c.len++] = carry + '0';
}
reverse(c.digits, c.digits + c.len);
return c;
}
减法
大整数的减法可以看成是两个二进制数的减法,也是从右往左逐位相减,记得处理借位。
// 大整数减法
struct BigInt sub(struct BigInt a, struct BigInt b) {
struct BigInt c = {0};
int borrow = 0; // 借位
int i, j;
for (i = a.len - 1, j = b.len - 1; i >= 0 || j >= 0; i--, j--) {
int x = i >= 0 ? a.digits[i] - '0' : 0;
int y = j >= 0 ? b.digits[j] - '0' : 0;
int diff = x - y - borrow;
if (diff < 0) {
diff += 2;
borrow = 1;
} else {
borrow = 0;
}
c.digits[c.len++] = diff + '0';
}
while (c.len > 1 && c.digits[c.len - 1] == '0') {
c.len--;
}
reverse(c.digits, c.digits + c.len);
return c;
}
乘法
大整数的乘法需要先将乘数和被乘数的每一位相乘,然后再将它们的乘积相加。这个过程中需要注意进位。
// 大整数乘法
struct BigInt mul(struct BigInt a, struct BigInt b) {
struct BigInt c = {0};
int i, j;
for (i = a.len - 1; i >= 0; i--) {
int carry = 0; // 进位
struct BigInt t = {0};
for (j = b.len - 1; j >= 0; j--) {
int x = a.digits[i] - '0';
int y = b.digits[j] - '0';
int product = x * y + carry;
t.digits[t.len++] = product % 2 + '0';
carry = product / 2;
}
if (carry) {
t.digits[t.len++] = carry + '0';
}
reverse(t.digits, t.digits + t.len);
for (j = 0; j < a.len - i - 1; j++) {
t.digits[t.len++] = '0';
}
c = add(c, t);
}
return c;
}
除法
大整数的除法可以用二分查找来实现。首先将被除数左移,直到它的长度不小于除数的长度。然后每次将被除数减去除数的左移,直到被除数小于除数。这个过程中需要注意进位。
// 大整数除法
struct BigInt div(struct BigInt a, struct BigInt b) {
struct BigInt c = {0};
struct BigInt t = {0};
int i, j;
for (i = 0; i < a.len; i++) {
t.digits[t.len++] = a.digits[i];
if (compare(t, b) < 0) {
c.digits[c.len++] = '0';
continue;
}
int l = 1, r = 10;
while (l < r) {
int m = (l + r) >> 1;
struct BigInt tmp = mul(b, {0, {(char)(m + '0')}});
if (compare(tmp, t) <= 0) {
l = m + 1;
} else {
r = m;
}
}
c.digits[c.len++] = (char)(l - 1 + '0');
struct BigInt tmp = mul(b, {0, {(char)(l - 1 + '0')}});
t = sub(t, tmp);
}
while (c.len > 1 && c.digits[c.len - 1] == '0') {
c.len--;
}
reverse(c.digits, c.digits + c.len);
return c;
}
最后,附上完整的代码:
#include <stdio.h>
#include <string.h>
#define MAX_LEN 1000 // 大整数最大长度
struct BigInt {
int len; // 大整数的长度
char digits[MAX_LEN]; // 大整数的每一位,存放在字符数组中
};
// 将字符数组反转
void reverse(char *begin, char *end) {
while (begin < end) {
char tmp = *begin;
*begin = *end;
*end = tmp;
begin++;
end--;
}
}
// 比较两个大整数
int compare(struct BigInt a, struct BigInt b) {
if (a.len != b.len) {
return a.len - b.len;
}
for (int i = 0; i < a.len; i++) {
if (a.digits[i] != b.digits[i]) {
return a.digits[i] - b.digits[i];
}
}
return 0;
}
// 大整数加法
struct BigInt add(struct BigInt a, struct BigInt b) {
struct BigInt c = {0};
int carry = 0; // 进位
int i, j;
for (i = a.len - 1, j = b.len - 1; i >= 0 || j >= 0; i--, j--) {
int x = i >= 0 ? a.digits[i] - '0' : 0;
int y = j >= 0 ? b.digits[j] - '0' : 0;
int sum = x + y + carry;
c.digits[c.len++] = sum % 2 + '0';
carry = sum / 2;
}
if (carry) {
c.digits[c.len++] = carry + '0';
}
reverse(c.digits, c.digits + c.len);
return c;
}
// 大整数减法
struct BigInt sub(struct BigInt a, struct BigInt b) {
struct BigInt c = {0};
int borrow = 0; // 借位
int i, j;
for (i = a.len - 1, j = b.len - 1; i >= 0 || j >= 0; i--, j--) {
int x = i >= 0 ? a.digits[i] - '0' : 0;
int y = j >= 0 ? b.digits[j] - '0' : 0;
int diff = x - y - borrow;
if (diff < 0) {
diff += 2;
borrow = 1;
} else {
borrow = 0;
}
c.digits[c.len++] = diff + '0';
}
while (c.len > 1 && c.digits[c.len - 1] == '0') {
c.len--;
}
reverse(c.digits, c.digits + c.len);
return c;
}
// 大整数乘法
struct BigInt mul(struct BigInt a, struct BigInt b) {
struct BigInt c = {0};
int i, j;
for (i = a.len - 1; i >= 0; i--) {
int carry = 0; // 进位
struct BigInt t = {0};
for (j = b.len - 1; j >= 0; j--) {
int x = a.digits[i] - '0';
int y = b.digits[j] - '0';
int product = x * y + carry;
t.digits[t.len++] = product % 2 + '0';
carry = product / 2;
}
if (carry) {
t.digits[t.len++] = carry + '0';
}
reverse(t.digits, t.digits + t.len);
for (j = 0; j < a.len - i - 1; j++) {
t.digits[t.len++] = '0';
}
c = add(c, t);
}
return c;
}
// 大整数除法
struct BigInt div(struct BigInt a, struct BigInt b) {
struct BigInt c = {0};
struct BigInt t = {0};
int i, j;
for (i = 0; i < a.len; i++) {
t.digits[t.len++] = a.digits[i];
if (compare(t, b) < 0) {
c.digits[c.len++] = '0';
continue;
}
int l = 1, r = 10;
while (l < r) {
int m = (l + r) >> 1;
struct BigInt tmp = mul(b, {0, {(char)(m + '0')}});
if (compare(tmp, t) <= 0) {
l = m + 1;
} else {
r = m;
}
}
c.digits[c.len++] = (char)(l - 1 + '0');
struct BigInt tmp = mul(b, {0, {(char)(l - 1 + '0')}});
t = sub(t, tmp);
}
while (c.len > 1 && c.digits[c.len - 1] == '0') {
c.len--;
}
reverse(c.digits, c.digits + c.len);
return c;
}
int main() {
// 输入两个大整数
char a_str[MAX_LEN], b_str[MAX_LEN];
printf("请输入第一个大整数:");
scanf("%s", a_str);
printf("请输入第二个大整数:");
scanf("%s", b_str);
// 将字符串转换为大整数
struct BigInt a = {0};
for (int i = 0; a_str[i] != '\0'; i++) {
a.digits[a.len++] = a_str[i];
}
struct BigInt b = {0};
for (int i = 0; b_str[i] != '\0'; i++) {
b.digits[b.len++] = b_str[i];
}
// 计算加减乘除结果
struct BigInt sum = add(a, b);
struct BigInt diff = sub(a, b);
struct BigInt product = mul(a, b);
struct BigInt quotient = div(a, b);
// 输出结果
printf("a + b = ");
for (int i = 0; i < sum.len; i++) {
printf("%c", sum.digits[i]);
}
printf("\n");
printf("a - b = ");
for (int i = 0; i < diff.len; i++) {
printf("%c", diff.digits[i]);
}
printf("\n");
printf("a * b = ");
for (int i = 0; i < product.len; i++) {
printf("%c", product.digits[i]);
}
printf("\n");
printf("a / b = ");
for (int i = 0; i < quotient.len; i++) {
printf("%c", quotient.digits[i]);
}
printf("\n");
return 0;
}
原文地址: https://www.cveoy.top/t/topic/nJvF 著作权归作者所有。请勿转载和采集!