大数乘除法

大数乘除法

大数乘法

代码

/*
大整数乘法
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] = '\0' 
	

	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] = '\0';
	// 将 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] = '\0';
	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

posted @ 2021-11-08 23:56  lucky_doog  阅读(381)  评论(0)    收藏  举报