加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

大数运算

发布时间:2020-12-14 02:56:11 所属栏目:大数据 来源:网络整理
导读:? ? ? ?文章位操作实现加减乘除四则运算 ? ? ? ?当整数很大,在计算机可以表示的范围内无法通过常规的加减等运算计算时,这里介绍的大数运算是一种有效的计算方法。 ??????? 这里介绍一种方式:将大数表示为一个n进制的数组(分别将大数表示成十进制和N进制

? ? ? ?文章位操作实现加减乘除四则运算

? ? ? ?当整数很大,在计算机可以表示的范围内无法通过常规的加减等运算计算时,这里介绍的大数运算是一种有效的计算方法。

??????? 这里介绍一种方式:将大数表示为一个n进制的数组(分别将大数表示成十进制和N进制),介绍大数的加减乘三种运算。这里仅考虑了非负整数

一、将大数表示为10进制

使用C++

string AddLongInteger(string addend,string augend)
{
	if(addend.size() < augend.size())
 		return AddLongInteger(augend,addend);

	int i,j,temp,flag = 0;
 	for(i = addend.size() - 1,j = augend.size() - 1; i >= 0;i--,j--)
	{
		if(j >= 0)
			 temp = addend[i] - '0' + augend[j] - '0' + flag ;
 		else
			 temp = addend[i] - '0' + flag;
		if(temp > 9)
		{
 			flag = 1;
			temp %= 10;
 		}
 		else flag = 0;

		addend[i] = temp + '0';
	}

 	if(flag)
		addend = "1" + addend; 
 	return addend;
 }

int main()
{
	string str1,str2;
	 cin >> str1 >> str2;
	cout << AddLongInteger(str1,str2) << endl;
	return 0;
}

单独的实现函数

大数加法

const int maxn = 1001;
void BigdataAdd() {
	char data1_str[maxn],data2_str[maxn];
	int data1[maxn] = {0},data2[maxn]  = {0},data_sum[maxn]  = {0};  //这里初始化为0很重要,之后计算依赖于初始值
	int len_data1,len_data2,i; 
	scanf("%s",data1_str);              //由控制台读入第一个char数组形式的大数
	len_data1 = strlen(data1_str);
	for (i = 0; i < len_data1; ++i)      //将这个大数存入到int数组中,注意将char数组高位存入int数组地位,方便计算时对齐
		data1[i] = data1_str[len_data1 - i - 1] - '0';
	scanf("%s",data2_str);
	len_data2 = strlen(data2_str);
	for (i = 0; i < len_data2; i++)
		data2[i] = data2_str[len_data2 - i - 1] - '0';
	int max_len = len_data1 > len_data2 ? len_data1 : len_data2; //计算两个数中较大的长度值
	int flag = 0;                                            // flag:需要进位的值
	for (i = 0; i < max_len; ++i) {                          //加法运算
		data_sum[i] = (data1[i] + data2[i] + flag) % 10; //本位的数值
		flag = (data1[i] + data2[i] + flag) / 10;        //需要进位的数值
 	}
	printf("Sum: ");
	if (flag != 0) {                                         //考虑最高位是否进位
		data_sum[max_len] = 1;                          
		printf("%d",data_sum[max_len]);                 //输出计算结果最高位
	}
	for (i = max_len - 1; i >= 0; --i)                       //输出计算结果其他位
		printf("%d",data_sum[i]);
	printf("n");
}

int main() {
	BigdataAdd();
	return 0;
}

输出结果(一):
1
2
Sum: 3
请按任意键继续. . .

输出结果(二):



大数减法:

void BigdataSubtraction() {
	char data1_str[maxn],data2[maxn] = {0},data_sub[maxn] = {0};  //这里初始化为0很重要,之后计算依赖于初始值
	int len_data1,len_data2;
	scanf("%s",data1_str);
	scanf("%s",data2_str);	
	len_data1 = strlen(data1_str);
	len_data2 = strlen(data2_str);
	int bigdata;
	if (len_data1 > len_data2)  //判断哪个数大,将该数作为被减数
		bigdata = 1;
	else if (len_data1 < len_data2)
		bigdata = -1;
	else
		bigdata = strcmp(data1_str,data2_str);
	int i;
	if (bigdata >= 0) {
		for (i = 0; i < len_data1; ++i)
			data1[i] = data1_str[len_data1 - i - 1] - '0';
		for (i = 0; i < len_data2; i++)
			data2[i] = data2_str[len_data2 - i - 1] - '0';
	}
	else {
		for (i = 0; i < len_data2; ++i)
			data1[i] = data2_str[len_data2 - i - 1] - '0';
		for (i = 0; i < len_data1; i++)
			data2[i] = data1_str[len_data1 - i - 1] - '0';
	}

	int flag = 0;             //flag表示借位
	int max_len = len_data1 >= len_data2 ? len_data1 : len_data2;
	for (i = 0; i < max_len; ++i) {
		int this_sub = data1[i] - flag;
		data_sub[i] = this_sub - data2[i];
		if (data_sub[i] >= 0) {
			flag = 0;
		}
		else {
			flag = 1;
			data_sub[i] += 10;
		}
	}
	printf("Subtraction: ");
	if (bigdata < 0) //如果输入的第一个数小,则为结果添加负号
		printf("-");
	while (max_len > 1 && !data_sub[max_len - 1])
		max_len--;
	for (i = max_len - 1; i >= 0; --i)
		printf("%d",data_sub[i]);
	printf("n");
}

输出结果(一):

12
45
Subtraction: -33
请按任意键继续. . .

输出结果(二):


大数乘法:

这里的乘法操作是比较完善的,考虑了数据输入非法、乘数为负数、乘数为0时的输出形式等情况。

string Mutiplication(const string data1,const string data2) {
	if (data1 == "" || data2 == "") //非法输入
		return "";

	string result;
	int length_data1 = data1.size();
	int length_data2 = data2.size();
	
	vector<int> result_number(length_data1 +  length_data2 - 1,0);

	//处理有负数的情况,data1为负数则data1_end等于1,data2为负数则data2_end等于1
	int data1_end = 0,data2_end = 0;
	if (data1[0] - '-' == 0 && data2[0] - '-' == 0) {
		data1_end = 1;
		data2_end = 1;
	}
	else if (data1[0] - '-' == 0)
		data1_end = 1;
	else if (data2[0] - '-' == 0)
		data2_end = 1;
	else {}

	for (int i = length_data2 - 1; i >= data2_end; --i) {
		for (int j = length_data1 - 1; j >= data1_end; --j) {
			if (!isdigit(data1[j]) || !isdigit(data2[i])) {
				cerr << "invalid number";
				return "";
			}
			//result_number记录乘法过程中每一位
			result_number[i + j] += (data2[i] - '0') * (data1[j] - '0');
		}
	}

	//处理进位并将结果存到字符串result
	int carry = 0;
	for (int i = result_number.size() - 1; i >= 0; --i) {
		result_number[i] += carry;
		carry = result_number[i] / 10;
		result = string(1,result_number[i] % 10 + '0') + result;
	}

	if (carry > 0) //最高位的进位
		result = string(1,carry + '0') + result;

	//下面几行处理有乘数为0的情况,如果不处理,会出现:
	//1234 * 0 = 0000的情况
	string::iterator iter = result.begin();
	//如果乘法结果的前n - 1位为0,则将其删除,只保留最后一位
	while (*iter - '0' == 0 && iter < result.end() - 1) {
		iter = result.erase(iter);
	}

	//如果结果为负数则在结果字符串中添加负号
	if (data1_end ^ data2_end)
		result = "-" + result;
	return result;
}

int main() {
	string a;
	string b;
	while (cin >> a >> b)
		cout << "result: " << Mutiplication(a,b) << endl;
}



以上C语言的实现方式只是做了几个单独的测试,各个函数间代码的重复率很高,没有整合,这里仅是给出了大整数运算的实现方法。本文第三部分给出了这部分代码的C++类实现方式。

二、将大数表示为N进制数组

??????? N的取值越大,数组大小越小,这样可以缩短运算时间以及空间复杂度,提高运算效率。在32位系统中,N可以取2的32次方,此时一位的大小为0~0xffffffff.

?????? 当进行加法和乘法运算会进位,则可能要判断溢出,因此,选用long long型(64位)。这里的运算思想和第一部分十进制的运算思想是一致的。

1. 加法运算:

??????? 运用”竖式计算“的思想,首先将两个操作数的低位对齐,如果本位所加的结果大于0xffffffff - 1才做进位(flag)处理,否则不进位。

计算0x12 0x2 + 0xffffffff 0xfffffff:

???? (1)个位:0x2 + 0xffffffff 大于0xfffffff,所以进位,本位结果为1,进位标志flag = 1;

???? (2)十位:0x12 + 0xffffffff + flag大于0xfffffff,所以进位,本位结果为12,flag = 1;

???? (3)计算第三位,两个加数均为0,进位为1,所以本位结果为1;

??????? 最终计算结果为1 12 1。


2.减法运算:

计算0x1 0x1 0x1 - 0xffffff:

????? (1)0x1 - 0xfffffff 小于0, 需要借位,本位为2;

????? (2)十位被个位借了1,因此本位结果为0;

????? (3)百位结果为1;

??????? 最终结果为102。


3. 乘法运算:

计算0x1 0x1 0x1 * 0xffffff 0xfffffff:

??????? (1)个位:0x1 0x1 0x1 * 0xffffffff = 0xffffffff0xffffffff0xffffffff

??????? (2)十位:0x1 0x1 0x1 * 0xffffffff =0xffffffff0xffffffff0xffffffff,因为这是十位,所以结果为0xffffff0xffffff 0xffffff 0x0;

????????? 最终结果:0xffffffff0xffffffff0xffffffff 0x0 + 0xffffffff0xffffffff0xffffffff = 1 0 0xffffffff?0xfffffffe0xffffffff。


三、第一部分的C++实现:

const int maxn = 1001;
class BigData {
?? ?int len;
?? ?int data[maxn];
?? ?BigData Sub(const BigData& a,const BigData& b) {
?? ??? ?int i;
?? ??? ?BigData result;
?? ??? ?int flag = 0;
?? ??? ?for (i = 0; i < a.len; ++i) {
?? ??? ??? ?int this_sub = a.data[i] - flag;
?? ??? ??? ?result.data[i] = this_sub - b.data[i];
?? ??? ??? ?if (result.data[i] >= 0)
?? ??? ??? ??? ?flag = 0;
?? ??? ??? ?else {
?? ??? ??? ??? ?flag = 1;
?? ??? ??? ??? ?result.data[i] += 10;
?? ??? ??? ?}
?? ??? ??? ?result.len = a.len;
?? ??? ?}
?? ??? ?result.clean();
?? ??? ?return result;
?? ?}

?? ?void clean() {
?? ??? ?while (len > 1 && !data[len - 1])
?? ??? ??? ?len--;
?? ?}

?? ?string str() const {
?? ??? ?string res = "";
?? ??? ?int i;
?? ??? ?for (i = 0; i < len; i++)
?? ??? ??? ?res = (char)(data[i] + '0') + res;
?? ??? ?if (res.empty())
?? ??? ??? ?res = "0";
?? ??? ?return res;
?? ?}

public:
?? ?BigData() {
?? ??? ?memset(data,sizeof(data));
?? ??? ?len = 1;
?? ?}

?? ?BigData(int num) {
?? ??? ?*this = num;
?? ?}

?? ?BigData(const char* num) {
?? ??? ?*this = num;
?? ?} 

?? ?BigData& operator=(int num) {
?? ??? ?char data[maxn];
?? ??? ?sprintf(data,"%d",num);
?? ??? ?*this = data;
?? ??? ?return *this;
?? ?}

?? ?BigData& operator=(const char *num) {
?? ??? ?len = strlen(num);
?? ??? ?int i;
?? ??? ?for (i = 0; i < len; ++i)
?? ??? ??? ?data[i] = num[len - i - 1] - '0';
?? ??? ?return *this;
?? ?}

?? ?BigData operator+(const BigData& b) const {
?? ??? ?BigData c;
?? ??? ?c.len = 0;
?? ??? ?int i,flag = 0;
?? ??? ?int max_len = len > b.len ? len : b.len;
?? ??? ?for (i = 0; i < max_len; ++i) {
?? ??? ??? ?int sum = (flag + data[i] + b.data[i]);
?? ??? ??? ?c.data[c.len++] = sum % 10;
?? ??? ??? ?flag = sum / 10;
?? ??? ?}
?? ??? ?if (flag != 0)
?? ??? ??? ?c.data[c.len++] = 1;
?? ??? ?c.clean();
?? ??? ?return c;
?? ?}

?? ?BigData& operator+=(const BigData& b) {
?? ??? ?*this = *this + b;
?? ??? ?return *this;
?? ?}
?? ?
?? ?BigData& operator-=(const BigData& b) {
?? ??? ?*this = *this - b;
?? ??? ?return *this;
?? ?}

?? ?bool operator<(const BigData& b) const {
?? ??? ?if (len != b.len)
?? ??? ??? ?return len < b.len;
?? ??? ?int i;
?? ??? ?for (i = len - 1; i >= 0; --i) {
?? ??? ??? ?if (data[i] != b.data[i])
?? ??? ??? ??? ?return data[i] < b.data[i];
?? ??? ?}
?? ??? ?return false;
?? ?}

?? ?bool operator>(const BigData& b) const {
?? ??? ?return b < *this;
?? ?}

?? ?bool operator<=(const BigData& b) const {
?? ??? ?return !(*this > b);
?? ?}

?? ?bool operator>=(const BigData& b) const {
?? ??? ?return !(*this < b);
?? ?}

?? ?bool operator==(const BigData& b) const {
?? ??? ?return !(*this > b) && !(*this < b);
?? ?}

?? ?BigData operator-(const BigData& b) {
?? ??? ?BigData c;
?? ??? ?c.len = 0;
?? ??? ?if (*this == b) {
?? ??? ??? ?c.data[++c.len] = 0;
?? ??? ??? ?return c;
?? ??? ?}
?? ??? ?else if (*this > b) {
?? ??? ??? ?c = Sub(*this,b);
?? ??? ?}
?? ??? ?else {
?? ??? ??? ?c = Sub(b,*this);
?? ??? ??? ?c.data[c.len++] = '-' - '0';
?? ??? ?}
?? ??? ?return c;
?? ?}

?? ?BigData operator*(const BigData& b) {
?? ??? ?int i,flag;
?? ??? ?BigData result;
?? ??? ?for (i = 0; i < len; ++i) {
?? ??? ??? ?for (j = 0; j < b.len; ++j) {
?? ??? ??? ??? ?result.data[i + j] = data[i] * b.data[j];
?? ??? ??? ?}
?? ??? ?}
?? ??? ?result.len = len + b.len;
?? ??? ?for (i = 0; i <result.len; ++i) {
?? ??? ??? ?result.data[i + 1] += result.data[i] / 10;
?? ??? ??? ?result.data[i] %= 10;
?? ??? ?}
?? ??? ?result.clean();
?? ??? ?return result;
?? ?}

?? ?friend ostream& operator<<(ostream& out,const BigData& bd) {
?? ??? ?out << bd.str();
?? ??? ?return out;
?? ?}

?? ?friend istream& operator>>(istream& in,BigData& bd) {
?? ??? ?string s;
?? ??? ?in >> s;
?? ??? ?bd = s.c_str();
?? ??? ?return in;
?? ?}
};

int main() {
?? ?BigData a,b;
?? ?cin >> a >> b;
?? ?cout << "a: " << a << endl;
?? ?cout << "b: " << b << endl;
?? ?cout << "a+b: " << a + b<< endl;
?? ?cout << "a-b: " << a - b << endl;
?? ?cout << "a*b: " << a * b << endl;
?? ?a += b;
?? ?cout << "a += b: " << a << endl;
?? ?a -= b;
?? ?cout << "a -= b: " << a << endl;
?? ?return 0;
}
输出结果:

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读