zoukankan      html  css  js  c++  java
  • 挑战面试编程:大整数的加、减、乘、除

                         挑战面试编程:大整数的加、减、乘、除

        一切都是有限的,哪怕是看起来无限的时间或空间都非常可能是有限的。在计算机中内置类型的加、减、乘、除都是有限的。我们来实现一个“无限”的大整数加、减、乘、除。

    下面使用C++代码实现

    #include <iostream>
    #include <string>
    using namespace std;
    //大整数的加减乘除
    string add_int(string, string);
    string sub_int(string, string);
    string mul_int(string, string);
    string div_int(string, string);
    string mod_int(string, string);
    string divide_int(string, string, int);
    
    inline int compare(string s1, string s2)
    {
    	if (s1.size() < s2.size())
    		return -1;
    	else if (s1.size() > s2.size())
    		return 1;
    	else
    		return s1.compare(s2);
    }
    /*
    大整数加法
    本质上仅仅处理:两个正数相加,如 "123" + "234"
    其他情况需转化
    1. 正加负 => "123" + "-234"  = "123" - "234" 转化为减法
    2. 负加正 => "-234" + "123"  = "123" - "234"
    3. 负加负 => "-123" + "-234" = -("123" + "234")
    */
    string add_int(string s1, string s2)
    {
    	if (s1 == "0")
    		return s2;
    	if (s2 == "0")
    		return s1;
    	if (s1[0] == '-')
    	{
    		if (s2[0] == '-')
    		{
    			return "-" + add_int(s1.erase(0, 1), s2.erase(0, 1));  //情况三
    		}
    		else
    		{
    			return sub_int(s2, s1.erase(0, 1));  //情况二
    		}
    	}
    	if (s2[0] == '-')
    	{
    		return sub_int(s1, s2.erase(0, 1));  //情况一
    	}
    	//处理本质情况
    	string::size_type i, size1, size2;
    	size1 = s1.size();
    	size2 = s2.size();
    	if (size1 < size2)
    	{
    		for (i = 0; i < size2 - size1; i++)   //在s1左边补零
    			s1 = "0" + s1;
    	}
    	else
    	{
    		for (i = 0; i < size1 - size2; i++)   //在s2左边补零
    			s2 = "0" + s2;
    	}
    
    	int n1, n2;
    	n2 = 0;
    	size1 = s1.size();
    	size2 = s2.size();
    	string res;
    	for (i = size1 - 1; i != 0; i--)   //从最低位加起
    	{
    		n1 = (s1[i] - '0' + s2[i] - '0' + n2) % 10;  //n1代表当前位的值
    		n2 = (s1[i] - '0' + s2[i] - '0' + n2) / 10;  //n2代表进位
    		res = char(n1 + '0') + res;
    	}
    	/*上述循环不能处理第0位的原因在于i的类型是string::size_type,它是非负类型*/
    	//对于第0位单独处理
    	n1 = (s1[0] - '0' + s2[0] - '0' + n2) % 10;
    	n2 = (s1[0] - '0' + s2[0] - '0' + n2) / 10;
    	res = char(n1 + '0') + res;
    
    	if (n2 == 1)
    		res = "1" + res;
    
    	return res;
    }
    /*
    大整数减法
    本质上仅仅处理:两整数相减,而且是一大减一小:"1234" - "234"
    其他情况需转化
    1. 小正减大正 => "234" - "1234" = -("1234" - "234")
    2. 正减负 => "1234" - "-234" = "1234" + "234"
    3. 负减正 => "-1234" - "234" = -("1234" + "234")
    4. 负减负 => "-1234" - "-234" = "234" - "1234" = -("1234" - "234")
    */
    string sub_int(string s1, string s2)
    {
    	if (s2 == "0")
    		return s1;
    	if (s1 == "0")
    	{
    		if (s2[0] == '-')
    			return s2.erase(0, 1);
    		return "-" + s2;
    	}
    
    	if (s1[0] == '-')
    	{
    		if (s2[0] == '-')
    		{
    			return sub_int(s2.erase(0, 1), s1.erase(0, 1));   //情况四
    		}
    		return "-" + add_int(s1.erase(0, 1), s2);   //情况三
    	}
    
    	if (s2[0] == '-')
    		return add_int(s1, s2.erase(0, 1));  //情况二
    
    	//调整s1与s2的长度
    	string::size_type i, size1, size2;
    	size1 = s1.size();
    	size2 = s2.size();
    	if (size1 < size2)
    	{
    		for (i = 0; i < size2 - size1; i++)   //在s1左边补零
    			s1 = "0" + s1;
    	}
    	else
    	{
    		for (i = 0; i < size1 - size2; i++)   //在s2左边补零
    			s2 = "0" + s2;
    	}
    	int t = s1.compare(s2);
    
    	if (t < 0)   //s1与s2的size同样。但 s1 < s2
    		return "-" + sub_int(s2, s1);
    
    	if (t == 0)
    		return "0";
    
    	//处理本质情况:s1 > s2
    	string res;
    	string::size_type j;
    	for (i = s1.size() - 1; i != 0; i--)
    	{
    		if (s1[i] < s2[i])   //不足,需向前借一位
    		{
    			j = 1;
    			while (s1[i - j] == '0')
    			{
    				s1[i - j] = '9';
    				j++;
    			}
    			s1[i - j] -= 1;
    			res = char(s1[i] + ':' - s2[i]) + res;
    		}
    		else
    		{
    			res = char(s1[i] - s2[i] + '0') + res;
    		}
    	}
    	res = char(s1[0] - s2[0] + '0') + res;
    	//去掉前导零
    	res.erase(0, res.find_first_not_of('0'));
    	return res;
    }
    string mul_int(string s1, string s2)
    {
    	if (s1 == "0" || s2 == "0")
    		return "0";
    	//sign是符号位
    	int sign = 1;
    	if (s1[0] == '-')
    	{
    		sign *= -1;
    		s1.erase(0, 1);
    	}
    	if (s2[0] == '-')
    	{
    		sign *= -1;
    		s2.erase(0, 1);
    	}
    
    	string::size_type size1, size2;
    	string res, temp;
    	size1 = s1.size();
    	size2 = s2.size();
    	//让s1的长度最长
    	if (size1 < size2)
    	{
    		temp = s1;
    		s1 = s2;
    		s2 = temp;
    		size1 = s1.size();
    		size2 = s2.size();
    	}
    
    	int i, j, n1, n2, n3, t;
    	for (i = size2 - 1; i >= 0; i--)
    	{
    		temp = "";
    		n1 = n2 = n3 = 0;
    		for (j = 0; j < size2 - 1 - i; j++) temp = "0" + temp;
    		n3 = s2[i] - '0';
    		for (j = size1 - 1; j >= 0; j--)
    		{
    			t = (n3*(s1[j] - '0') + n2);
    			n1 = t % 10;  //n1记录当前位置的值
    			n2 = t / 10;  //n2记录进位的值
    			temp = char(n1 + '0') + temp;
    		}
    		if (n2)
    			temp = char(n2 + '0') + temp;
    		res = add_int(res, temp);
    	}
    	if (sign == -1)
    		return "-" + res;
    	return res;
    }
    string divide_int(string s1, string s2, int flag)  //flag=1,返回商;flag=0,返回余数
    {
    	string quotient, residue;
    	if (s2 == "0")
    	{
    		quotient = residue = "error";
    		if (flag == 1)
    			return quotient;
    		else
    			return residue;
    	}
    	if (s1 == "0")
    	{
    		quotient = residue = "0";
    		if (flag == 1)
    			return quotient;
    		else
    			return residue;
    	}
    	//sign1是商的符号,sign2是余数的符号
    	int sign1, sign2;
    	sign1 = sign2 = 1;
    	if (s1[0] == '-')
    	{
    		sign1 *= -1;
    		sign2 = -1;
    		s1.erase(0, 1);
    	}
    	if (s2[0] == '-')
    	{
    		sign1 *= -1;
    		s2.erase(0, 1);
    	}
    
    	if (compare(s1, s2) < 0)
    	{
    		quotient = "0";
    		residue = s1;
    	}
    	else if (compare(s1, s2) == 0)
    	{
    		quotient = "1";
    		residue = "0";
    	}
    	else
    	{
    		string temp;
    		string::size_type size1, size2;
    		size1 = s1.size();
    		size2 = s2.size();
    		int i;
    		if (size2 > 1) temp.append(s1, 0, size2 - 1);
    
    		for (i = size2 - 1; i < size1; i++)
    		{
    			temp = temp + s1[i];
    			//试商
    			for (char c = '9'; c >= '0' ; c--)
    			{
    				string t = mul_int(s2, string(1, c));
    
    				string s = sub_int(temp, t);
    
    				if (s == "0" || s[0] != '-')
    				{
    					temp = s;
    					quotient = quotient + c;
    					break;
    				}
    			}
    		}
    		residue = temp;
    	}
    	//去除前导零
    	quotient.erase(0, quotient.find_first_not_of('0'));
    	residue.erase(0, residue.find_first_not_of('0'));
    	if (sign1 == -1)
    	{
    		quotient = "-" + quotient;
    	}
    	if (sign2 == -1)
    	{
    		if (residue.empty())
    			residue = "0";
    		else
    			residue = "-" + residue;
    	}
    
    	if (flag == 1) return quotient;
    	else return residue;
    }
    string div_int(string s1, string s2)
    {
    	return divide_int(s1, s2, 1);
    }
    string mod_int(string s1, string s2)
    {
    	return divide_int(s1, s2, 0);
    }
    int main(void)
    {
    	string s1, s2;
    	char op;
    	while (cin >> s1 >> op >> s2)
    	{
    		switch (op)
    		{
    		case '+':cout << add_int(s1, s2) << endl; break;
    		case '-':cout << sub_int(s1, s2) << endl; break;
    		case '*':cout << mul_int(s1, s2) << endl; break;
    		case '/':cout << div_int(s1, s2) << endl; break;
    		case '%':cout << mod_int(s1, s2) << endl; break;
    		default:
    			cout << "The operator is error!" << endl; break;
    		}
    	}
    	return 0;
    }

    c语言实现大整数加法的实例

    #include <stdio.h>
    #include <string.h>
    #define MAXLEN 1000
    char a1[MAXLEN];
    char a2[MAXLEN];
    static int v1[MAXLEN];
    static int v2[MAXLEN];
    static int v3[MAXLEN];
    int i, j, n, L, z;
    void main(void) {
    	scanf("%d", &n);
    	for (j = 0; j < n; j++) {
    		scanf("%s%s", a1, a2);
    		L = strlen(a1);
    		for (i = 0; i < L; i++) v1[i] = a1[L - 1 - i] - '0';  //下标越小。位数越高
    		L = strlen(a2);
    		for (i = 0; i < L; i++) v2[i] = a2[L - 1 - i] - '0';
    		for (i = 0; i < MAXLEN; i++) v3[i] = v1[i] + v2[i];
    		for (i = 0; i < MAXLEN; i++) {
    			if (v3[i] >= 10) {
    				v3[i + 1] += 1;
    				v3[i] = v3[i] % 10;
    			}
    		}
    		printf("Case %d:
    ", j + 1);
    		printf("%s + %s = ", a1, a2);
    		z = 0;
    		for (i = MAXLEN - 1; i >= 0; i--) {
    			if (z == 0) {
    				if (v3[i] != 0) {
    					printf("%d", v3[i]);
    					z = 1;
    				}
    			}
    			else {
    				printf("%d", v3[i]);
    			}
    		}
    		if (z == 0) printf("0");
    		printf("
    ");
    	}
    	getchar();
    	getchar();
    }
    //Sample Input
    //3
    //0 0
    //1 2
    //112233445566778899 998877665544332211
    //
    //Sample Output
    //Case 1:
    //0 + 0 = 0
    //Case 2:
    //1 + 2 = 3
    //Case 3:
    //112233445566778899 + 998877665544332211 = 1111111111111111110
       



    代码下载

    大整数的加、减、乘、除 C++


    全部内容的文件夹



  • 相关阅读:
    2020.2.5随笔
    2020.2.4
    2020.2.3随笔
    2020.2.2随笔
    2020/2/1随笔
    python3 百度AI-v3之 人脸对比 & 人脸检测 & 在线活体检测 接口
    python:Json模块dumps、loads、dump、load介绍
    python3之selenium.webdriver 库练习自动化谷歌浏览器打开百度自动百度关键字
    python之https爬虫出现 SSL: CERTIFICATE_VERIFY_FAILED (同时打开fiddler就会出现)
    调试python 程序的几种方法总结
  • 原文地址:https://www.cnblogs.com/zsychanpin/p/7064314.html
Copyright © 2011-2022 走看看