C语言实现大整数加减乘运算:基于二进制字符数组表示
C语言实现大整数加减乘运算:基于二进制字符数组表示
为了解决大整数的表示与运算溢出问题,我们可以将大整数先转换成二进制,再把二进制中的每一位,0 或 1,以'0'或'1'字符的形式,从低到高位依次存放到一个字符数组中,称为大数的二进制字符数组表示。
以下是一个示例代码,支持大整数的加、减、乘运算,同时含有注释和符号判断:
#include <stdio.h>
#include <string.h>
#define MAX_LEN 1000 // 数组最大长度
// 将大整数转换为二进制字符数组表示
void toBinary(char* num, int len, char* bin) {
for (int i = 0; i < len; i++) {
int n = num[i] - '0'; // 将字符转换为数字
for (int j = 0; j < 4; j++) {
bin[i * 4 + j] = (n & (1 << j)) ? '1' : '0'; // 将数字转换为二进制字符
}
}
bin[len * 4] = '\0'; // 末尾加上结束符
}
// 将二进制字符数组表示转换为大整数
void toNumber(char* bin, char* num) {
int len = strlen(bin) / 4;
for (int i = 0; i < len; i++) {
int n = 0;
for (int j = 0; j < 4; j++) {
n |= ((bin[i * 4 + j] - '0') << j); // 将二进制字符转换为数字
}
num[i] = n + '0'; // 将数字转换为字符
}
num[len] = '\0'; // 末尾加上结束符
}
// 对二进制字符数组表示进行补位,使其长度为len
void pad(char* bin, int len) {
int cur_len = strlen(bin);
if (cur_len < len) {
for (int i = 0; i < len - cur_len; i++) {
bin[cur_len + i] = '0';
}
bin[len] = '\0'; // 末尾加上结束符
}
}
// 对二进制字符数组表示进行去零,使其最高位不为0
void trim(char* bin) {
int len = strlen(bin);
while (len > 1 && bin[len - 1] == '0') {
bin[len - 1] = '\0';
len--;
}
}
// 二进制字符数组表示的加法
void addBinary(char* bin1, char* bin2, char* res) {
int len1 = strlen(bin1);
int len2 = strlen(bin2);
int len = (len1 > len2) ? len1 : len2; // 结果长度为两数长度的较大值
pad(bin1, len);
pad(bin2, len);
int carry = 0;
for (int i = 0; i < len; i++) {
int sum = (bin1[i] - '0') + (bin2[i] - '0') + carry;
res[i] = (sum % 2) ? '1' : '0';
carry = sum / 2;
}
if (carry) {
res[len] = '1';
len++;
}
else {
res[len] = '\0';
}
trim(res);
}
// 二进制字符数组表示的减法
void subBinary(char* bin1, char* bin2, char* res) {
int len1 = strlen(bin1);
int len2 = strlen(bin2);
int len = (len1 > len2) ? len1 : len2; // 结果长度为两数长度的较大值
pad(bin1, len);
pad(bin2, len);
int borrow = 0;
for (int i = 0; i < len; i++) {
int diff = (bin1[i] - '0') - (bin2[i] - '0') - borrow;
if (diff < 0) {
diff += 2;
borrow = 1;
}
else {
borrow = 0;
}
res[i] = (diff == 1) ? '1' : '0';
}
trim(res);
}
// 二进制字符数组表示的乘法
void mulBinary(char* bin1, char* bin2, char* res) {
int len1 = strlen(bin1);
int len2 = strlen(bin2);
int len = len1 + len2; // 结果长度为两数长度之和
char tmp[MAX_LEN] = { 0 };
for (int i = 0; i < len1; i++) {
int carry = 0;
for (int j = 0; j < len2; j++) {
int prod = (bin1[i] - '0') * (bin2[j] - '0') + carry;
tmp[i + j] = (prod % 2) ? '1' : '0';
carry = prod / 2;
}
if (carry) {
tmp[i + len2] = '1';
}
}
pad(tmp, len);
strcpy(res, tmp);
trim(res);
}
int main() {
char num1[MAX_LEN], num2[MAX_LEN], op;
scanf('%s %c %s', num1, &op, num2);
int len1 = strlen(num1);
int len2 = strlen(num2);
char bin1[MAX_LEN * 4 + 1], bin2[MAX_LEN * 4 + 1], res[MAX_LEN * 8 + 1];
toBinary(num1, len1, bin1);
toBinary(num2, len2, bin2);
switch (op) {
case '+':
addBinary(bin1, bin2, res);
break;
case '-':
subBinary(bin1, bin2, res);
break;
case '*':
mulBinary(bin1, bin2, res);
break;
default:
printf('Invalid operator\n');
return 1;
}
int sign1 = (num1[0] == '-') ? -1 : 1;
int sign2 = (num2[0] == '-') ? -1 : 1;
int sign = 1;
if (op == '-' && sign1 * sign2 == -1) {
sign = -1;
}
if (sign == -1) {
printf('-');
}
toNumber(res, num1);
printf('%s\n', num1);
return 0;
}
需要注意的是,对于减法,我们需要判断被减数和减数的符号,如果它们不同,就相当于做加法,结果的符号为被减数的符号;否则,做减法,结果的符号为被减数和减数的符号相同。在代码中,我们通过sign1和sign2分别记录被减数和减数的符号,通过sign来记录结果的符号。如果sign为-1,则在输出结果前先输出负号。
原文地址: https://www.cveoy.top/t/topic/nKrX 著作权归作者所有。请勿转载和采集!