大数乘除法
大数乘法
代码
/*
大整数乘法
https://blog.csdn.net/u010983881/article/details/77503519
拟乘法累加 - 改进
思路来源段落链接:
https://blog.csdn.net/u010983881/article/details/77503519#:~:text=%E7%AC%AC%E4%BA%8C%E7%A7%8D%E6%96%B9%E6%B3%95%E3%80%82-,2%E3%80%81%E6%A8%A1%E6%8B%9F%E4%B9%98%E6%B3%95%E7%B4%AF%E5%8A%A0%20-%20%E6%94%B9%E8%BF%9B,-%E7%AE%80%E5%8D%95%E6%9D%A5%E8%AF%B4%EF%BC%8C%E6%96%B9%E6%B3%95
*/
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
using namespace std;
// 将 ASCII 字符转换成对应的数
#define Char2Int(x) ((x) - 0x30)
// 将 数 转换成 ASCII 字符
#define Int2Char(x) ((x) + 0x30)
char * big_num_mutiply(char * a, char * b);
int main()
{
cout << big_num_mutiply("12345678", "12345678") << endl;;//预期输出 152,415,765,279,684
cout << big_num_mutiply("1234", "5678") << endl;//预期输出 7006652
cout << big_num_mutiply("123456789101112131415", "123456789101112131415") << endl;
//预期输出 15241578775156479157107515989284229902225
cout << big_num_mutiply("15241578775156479157107515989284229902225", "15241578775156479157107515989284229902225") << endl;
// 预期输出 232305723559300479424424097917104370511691764893690487487812974988368833059950625
return 0;
}
/*
a 是被乘数
b 是乘数
返回 a*b 结果字符串
目前只支持正整数
思路来源链接:
https://blog.csdn.net/u010983881/article/details/77503519#:~:text=%E7%AC%AC%E4%BA%8C%E7%A7%8D%E6%96%B9%E6%B3%95%E3%80%82-,2%E3%80%81%E6%A8%A1%E6%8B%9F%E4%B9%98%E6%B3%95%E7%B4%AF%E5%8A%A0%20-%20%E6%94%B9%E8%BF%9B,-%E7%AE%80%E5%8D%95%E6%9D%A5%E8%AF%B4%EF%BC%8C%E6%96%B9%E6%B3%95
*/
char * big_num_mutiply(char * a, char * b)
{
//a_len 是被乘数的位数 b_len 是乘数的位数
int a_len = strlen(a);
int b_len = strlen(b);
int res_len = a_len + b_len - 1;//乘积数字表示的位数是 乘数位数 + 被乘数位数 - 1
int increment = 0; //进位
int * res_int = new int[res_len];//乘积的数字表示 也是大端对齐 即 LSB 在 下标为 0 的位置
char * res_str_low = new char[res_len + 1];//乘积的字符串表示
//1)大端对齐 最高位放在 下标为 0 的位置 (进位除外)
//2)长度: res_len + 1 ,res_str[res_len] = ' '
memset(res_int, 0, res_len*sizeof(int));
// 乘数在外围,被乘数在内层
for (int j = b_len - 1; j >= 0; j--)
{
for (int i = a_len - 1; i >= 0; i--)
{
int temp = Char2Int(a[i]) * Char2Int(b[j]);
int index = i + j;// 临时结果在乘积中的位置下标
res_int[index] += temp;
}
}
res_str_low[res_len] = ' ';
// 将 res_int 转换成 res_str_low, 同时处理进位
for (int k = res_len - 1; k >= 0; k--)
{
res_int[k] += increment;
res_str_low[k] = Int2Char(res_int[k] % 10);
increment = res_int[k] / 10;
}
delete res_int;
//若有进位,则将其转换成字符串 ,并将进位字符串和低位字符串拼接起来
if (increment)
{
char * res_str_high = new char[res_len];// 用于保存进位
itoa(increment, res_str_high, 10);
strcat(res_str_high, res_str_low);
return res_str_high;
}
else
{
return res_str_low;
}
}
python 验证
a = 123456789101112131415
b = 123456789101112131415
c = a * b
print(c)
# 预期输出 15241578775156479157107515989284229902225
a = 15241578775156479157107515989284229902225
c = a * a
print(c)
# 预期输出 232305723559300479424424097917104370511691764893690487487812974988368833059950625
大数除法
代码
//大整数除法, 只考虑被除数很大的情况
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <assert.h>
//#include <limits.h>
using namespace std;
// 将 ASCII 字符转换成对应的数
#define Char2Int(x) ((x) - 0x30)
// 将 数 转换成 ASCII 字符
#define Int2Char(x) ((x) + 0x30)
// int 可以进行正常除法运算的最多位数 是 9
// 见 limits.h 里面 #define INT_MAX 2147483647
// 共 10位 , 最多可用的是 9 位
#define MAX_WIDTH 9
char * big_num_division(char * dividend, char * divisor);
int main()
{
cout << big_num_division("123456789101112131415", "8") << endl; //预期输出 15432098637639016426
cout << big_num_division("12345", "678910") << endl; //预期输出 0
cout << big_num_division("123456789101112131415", "3") << endl;// 预期输出 41152263033704043805
cout << big_num_division("1234567891011121314", "8") << endl; // 预期输出 154320986376390164
return 0;
}
// dividend 是被除数 divisor 是除数
char * big_num_division(char * dividend, char * divisor)
{
int dividend_len = strlen(dividend);
int divisor_len = strlen(divisor);
assert(divisor_len < MAX_WIDTH);// 默认除数很小,不超过范围
int divisor_int = atoi(divisor);
char * res_str = new char[dividend_len];//结果字符串
memset(res_str, 0, sizeof(char) * dividend_len);
// 当被除数位数小于等于除数时,直接返回字符串 "0"
if (dividend_len < divisor_len)
{
delete res_str;
return "0";
}
// 当被除数位数在 MAX_WIDTH 以内时,使用 atoll 将其转换成 int 进行正常的除法运算 ,返回结果字符串
if (dividend_len <= MAX_WIDTH)
{
itoa(atoi(dividend)/atoi(divisor), res_str, 10);
return res_str;
}
// 当被除数位数多于 MAX_WIDTH 时,模拟手动竖式除法进行计算
int i = 0;
int j = 0;
int remainder = 0;
int quotient = 0;
while (quotient == 0)//去除开头的 0
{
quotient = (Char2Int(dividend[i]) + remainder * 10) / divisor_int;
remainder = (Char2Int(dividend[i]) + remainder * 10) % divisor_int;
i++;
if (quotient)
res_str[j++] = Int2Char(quotient);
}
for (; i < dividend_len; i ++)
{
quotient = (Char2Int(dividend[i]) + remainder * 10) / divisor_int;
remainder = (Char2Int(dividend[i]) + remainder * 10) % divisor_int;
res_str[j++] = Int2Char(quotient);
}
res_str[j] = ' ';
return res_str;
}
python 验证
c = 16151413121110987654321 // 123456789101112131415
print('16151413121110987654321 // 123456789101112131415 = %u' % c)
# 预期输出 130
c = 123456789101112131415//8
print('123456789101112131415//8 = %u' % c)
# 预期输出 15432098637639016426
c = 123456789101112131415//3
print('123456789101112131415//3 = %u' % c)
# 预期输出 41152263033704043805
c = 1234567891011121314//8
print('1234567891011121314//8 = %u' % c)
# 预期输出 154320986376390164