大数问题

剑指offer面试题12:打印1到最大的n位数

因为没有说明n的大小,所以有可能long long型也无法存下这个n位数,所以考虑大数问题,将其存储为字符数组或字符串。主要包括如何在字符串上模拟加法和如何把字符串打印出来。

void Print1ToMaxOfNDigits_1(int n)
{
	if (n <= 0)
		return;
	char* number = new char[n + 1];
	memset(number, '0', n);
	number[n] = '\0';
	while (!Increment(number))
	{
		PrintNumber(number);
	}
	delete[]number;
}

模拟字符加法要注意怎么判断已经达到最大的n位数,因为当达到最大的n位数后,再加一的话,第一个‘9’(第0位)会产生进位,而其他时候第一位均不会产生进位,所以以此来判断。

bool Increment(char* number)
{
	bool isOverflow = false;
	int nTakeOver = 0;
	int nLength = strlen(number);
	for (int i = nLength - 1; i >= 0; --i)
	{
		int nSum = number[i] - '0' + nTakeOver;
		if (i == nLength - 1)
			nSum++;
		if (nSum >= 10)
		{
			if (i == 0)
				isOverflow = true;
			else
			{
				nSum -= 10;
				nTakeOver = 1;
				number[i] = nSum + '0';
			}
		}
		else
		{
			number[i] = nSum + '0';
			break;
		}
	}
	return isOverflow;
}

打印字符串要注意当开头为‘0’的时候,根据习惯是不打印出来的,如‘098’,打印为98。

void PrintNumber(char* number)
{
	bool isBegining0 = true;
	int nLength = strlen(number);
	for (int i = 0; i < nLength; ++i)
	{
		if (isBegining0&&number[i] != '0')
			isBegining0 = false;
		if (!isBegining0)
			printf("%c", number[i]);
	}
	printf("\t");
}
第二种思路是把问题转换成数字排列,n位所有十进制数其实是n个0到9的全排列。所以只要把每一位从0到9排列一遍就可以得到所有的数了。

void Print1ToMaxOfNDigits_2(int n)
{
	if (n <= 0)
		return;
	char* number =new char[n + 1];
	number[n] = '\0';
	for (int i = 0; i < 10; ++i)
	{
		number[0] = i + '0';
		Print1ToMaxDigitsRecursively(number, n, 0);
	}
	delete[]number;
		
}

void Print1ToMaxDigitsRecursively(char* number, int length, int index)
{
	if (index == length - 1)
	{
		PrintNumber(number);
		return;
	}
	for (int i = 0; i < 10; ++i)
	{
		number[index + 1] = i + '0';
		Print1ToMaxDigitsRecursively(number, length, index + 1);
	}
		
}

相关题目:实现任意两个整数的加法

杭电ACM 1002题目

Input
The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line consists of two positive integers, A and B. Notice that the integers are very large, that means you should not process them by using 32-bit integer. You may assume the length of each integer will not exceed 1000.
 

Output
For each test case, you should output two lines. The first line is "Case #:", # means the number of the test case. The second line is the an equation "A + B = Sum", Sum means the result of A + B. Note there are some spaces int the equation. Output a blank line between two test cases.
 

Sample Input

2 1 2 112233445566778899 998877665544332211
 

Sample Output

Case 1: 1 + 2 = 3 Case 2: 112233445566778899 + 998877665544332211 = 1111111111111111110

解法:先在较短的数前填充‘0’,使得两个整数长度一样,然后从最后一位开始,逐位相加,并加上从上一次得到的进位,相加结束后,要单独判断进位是否为1,若为1,则在结果前面加上‘1’,否则不处理。

#include
#include
#include


using namespace std;


string addtwonumbers(string num1,string num2)
{
	int length;
	if (num1.length() > num2.length())
	{
		length = num1.length();
		string temp(num1.length() - num2.length(), '0');
		num2 = temp + num2;
	}
	else
	{
		length = num2.length();
		string temp(num2.length() - num1.length(), '0');
		num1 = temp + num1;
	}
	string sum(length, '0');
	int carry = 0;//进位
	for (int i = length - 1; i >= 0; --i)
	{
		int nSum = num1[i] - '0' + num2[i] - '0' + carry;
		sum[i] = nSum % 10 + '0';
		carry = (nSum > 9);
	}
	if (carry == 1)
		sum = '1' + sum;
	return sum;
}

int main()
{
		int t;    //the number of test cases;
		cin >> t;
		string *a = new string[t];    //use the dynamic array when not knowing the dimension before compiling;
		string *b = new string[t];
		string *sum = new string[t];
		for (int i = 0; i != t; ++i)
		{
			cin >> a[i] >> b[i];
			sum[i] = addtwonumbers(a[i], b[i]);
		}
			for (int i = 0; i != t; ++i){
				cout << "Case " << i + 1 << ":\n"
					<< a[i] << " + " << b[i] << " = " << sum[i] << endl;
				if (i

进一步问题,该代码只实现的两个正数相加,没有考虑输入中有负数的情况。

下面考虑加数中有负数的情况,若两个加数都是负数,则直接相加再在前面加个负号就可以了。若只有其中一个为负数,又分为两种情况,若正数绝对值大于负数,则用正数加上负数,最高位不会出现借位的情况,此时结果是正数;若正数小于负数,此时最高位还需进一步借位,我们在此假设Sub1长度不足Sub2长度的部分填充0,以“123”-‘456789’为例,如下见图所示,最终结果应该是“456666”,还要加上负号。

大数问题_第1张图片

上图可以理解为:

Sub1-Sub2=-(-(Sub1-Sub2))=-(-(基数+Sub1-Sub2-基数))=-(基数-(基数+Sub1-Sub2))

string BigMiunsSmall(string big, string small)//大数减小数(正数)
{
	int length = big.length();
	string temp(big.length() - small.length(), '0');
	small = temp + small;
	string minus(length, '0');
	int borrow = 0;//借位
	for (int i = length - 1; i >= 0; --i)
	{
		int nMinus = big[i] - small[i] - borrow;
		cout << nMinus << endl;
		if (nMinus < 0)
		{
			nMinus += 10;
			borrow = 1;
			minus[i] = nMinus + '0';
		}
		else
		{
			borrow = 0;
			minus[i] = nMinus + '0';
		}
	}
	return minus;
}
string addtwonumbers(string num1, string num2)
{
	int length;
	int flagNum1 = 1;
	int flagNum2 = 1;
	if (num1[0] == '-'&&num1[0] == '-')
	{
		flagNum1 = -1;
		flagNum2 = -1;

	}
	else if (num1[0] == '-')
	{
		num2 = '+' + num2;
		flagNum1 = -1;
	}
	else if (num2[0] == '-')
	{
		num1 = '+' + num1;
		flagNum2 = -1;
	}
	else
	{
		num1 = '+' + num1;
		num2 = '+' + num2;
	}
	if (num1.length() > num2.length())
	{
		length = num1.length();
		string temp(num1.length() - num2.length(), '0');
		num2 = num2[0] + temp+num2.substr(1, num2.length() - 1);
	}
	else
	{
		length = num2.length();
		string temp(num2.length() - num1.length(), '0');
		num1 = num1[0] + temp+ num1.substr(1, num1.length() - 1);
	}
	
	string sum(length - 1, '0');

	int carry = 0;//进位
	
	
		if (flagNum1*flagNum2 == 1)
		{
			for (int i = length - 1; i >= 1; --i)
			{
				int nSum = num1[i] - '0' + num2[i] - '0' + carry;
				if (nSum >= 10)
				{
					nSum -= 10;
					carry = 1;
					sum[i - 1] = nSum + '0';
				}
				else
				{
					carry = 0;
					sum[i - 1] = nSum + '0';
				}
			}
			if (carry == 1)
				sum = '1' + sum;
			if (flagNum1 == -1 && flagNum2 == -1)
				sum = '-' + sum;
		}
		else
		{
			for (int i = length - 1; i >= 1; --i)
			{
				
				int nSum = flagNum1*(num1[i] - '0') + flagNum2*(num2[i] - '0') + carry;
				
				if (nSum < 0)
				{
					nSum += 10;	
					carry = -1;
					sum[i-1] = nSum + '0';

				}
				else
				{
					carry = 0;
					sum[i-1] = nSum + '0';
				}
			}
			if (carry == -1)
			{
				string borrow(length, '0');
				borrow[0] = '1';
				sum = BigMiunsSmall(borrow, sum);
				sum[0] = '-';
			}
		}
	
	return sum;
}


参考文献:

http://www.cnblogs.com/ziqiao/archive/2010/10/09/1846955.html

http://www.cnblogs.com/ballwql/archive/2013/04/20/3032090.html

你可能感兴趣的:(算法)