1. 程式人生 > >1007. 二哥領工資 (超大數求和)

1007. 二哥領工資 (超大數求和)

題目描述

二哥當了多年的助教,今天終於要發工資了!二哥正在高興之際,得知工資是分兩部分發放的。第一部分是這學期的工資,另一部分是之前所有學期的工資總和。而領取工資時,出納員會問二哥,兩部分工資加在一起是多少,如果二哥回答錯了,就只能領到這個學期的工資之前所有學期的勞動就白費了。

二哥從小道訊息得知,出納員是個對數字敏感的人,不能有一點差錯,所以二哥需要一個程式來幫他算出精確的工資總和。

輸入格式

輸入共兩行,每行是一個十進位制表示的工資金額(沒有正負號,小數點後有兩位數字)。

輸出格式

輸出共一行,即精確的工資總和(沒有正負號,小數點後有兩位數字)。

說明

工資金額的有效數字位數不超過200位,並保證有小數點。

Sample Input

123.45
543.21

Sample Output

666.66
***********************************************************************************************************************************

分析

       這個題的說明中,有效數字位數不超過200位,所以數值是一個超大的數,對目前普通電腦的記憶體有限,表達不了這麼大的數字。 

雖然用float,double型做不到,我們可以把它轉化為字串的形式,再按照普通的一位數加法來計算,設定一個進位,如果兩個一位數相加大於10,則進位為1,否則為0;

如何把在字元與數值之間轉換呢?

把 數字9轉化字元‘9’, 只要 9+‘0’就可以了 ,即 ‘9’(字元) =  9(數字)+ ‘0’(字元)。

把字元‘9’轉化為數字9,則用 ‘9’-‘0’, 即 9(數字)=‘9’(字元)-‘0’(字元)。

為什麼能這樣做呢,因為在ASCII碼錶中, 字元‘0’對應48, 字元‘9’對應57, 所以我們有

 ‘9’(字元) =  9(數字)+    ‘0’(字元)

     48           =     9           +         48

程式碼:

#include <iostream>
#include <string>
using namespace std;

int main()
{
	string before;  //往年的工資總和
	string thisOne; //今年的工貿
	string sum;    //總工資
	char temp;     //臨時變數
	char carray = 0;  //進位
	int lenBe = 0;    
	int lenTh = 0;
		
	cin>>before;
	cin>>thisOne;
	lenBe = before.size();
	lenTh = thisOne.size();
	
	//倒序   如把 123.45 變換成 54.321
	//為了方便從個位開始進位計算
	for(int i = 0; i < lenBe/2; i++)
	{
		temp = before[i];
		before[i] = before[lenBe-i-1];
		before[lenBe-i-1] = temp;
	}
	
	for(int i = 0 ; i < lenTh/2; i++)
	{
		temp = thisOne[i];
		thisOne[i] = thisOne[lenTh-i-1];
		thisOne[lenTh-i-1] = temp;
	}

	carray = 0;    //初始進位為0
	for(int i = 0; i < 2; i++)
	{
		
		char a = before[i] - '0';
		char b = thisOne[i] - '0';
		char c = a + b + carray;
		if(c>=10)
		{
			carray = 1;
			sum.push_back(c%10+'0');
		}
		else
		{
			sum.push_back(c+'0');
			carray = 0;
		}
	}
	sum.push_back('.');  //第三位為小數點,不參與運算
	
	if(lenBe>=lenTh)     //比較哪個數值的長度, 以前工資總和長度大
	{
		for(int i = 3; i < lenTh; i++)    //i = 3, 從倒序字串的小數點後第一位開始
		{
			char a = before[i] - '0';   //減 '0', 把字元型資料轉成數字型資料
			char b = thisOne[i] - '0';
			char c = a + b + carray;
			if(c>=10)     //相加和大於等於10,進位
			{
				carray = 1;
				sum.push_back(c%10+'0');  //加'0', 把數字型資料轉成字元型資料
			}
			else
			{
				sum.push_back(c+'0');
				carray = 0;
			}
		}
		for(int i = lenTh; i < lenBe; i++)
		{
			char b = before[i] - '0';
			char c = b + carray;
			if(c>=10)
			{
				carray = 1;
				sum.push_back(c%10+'0');
			}
			else
			{
				sum.push_back(c+'0');
				carray = 0;
			}
		}
		if(1==carray)   //最高位進1,則為1
		{
			sum.push_back('1');
		}
	}
	else  //這個學期工資總和長度大
	{
		for(int i = 3; i < lenBe; i++)
		{
			char a = before[i] - '0';
			char b = thisOne[i] - '0';
			char c = a + b + carray;
			if(c>=10)
			{
				carray = 1;
				sum.push_back(c%10+'0');
			}
			else
			{
				sum.push_back(c+'0');
				carray = 0;
			}
		}
		for(int i = lenBe; i < lenTh; i++)
		{
			char b = before[i] - '0';
			char c = b + carray;
			if(c>=10)
			{
				carray = 1;
				sum.push_back(c%10+'0');
			}
			else
			{
				sum.push_back(c+'0');
				carray = 0;
			}
		}
		if(1==carray)    
		{
			sum.push_back('1');
		}
	}
	
	//倒序
	int lenSum = sum.size();
	for(int i = 0; i < lenSum/2; i++)
	{
		temp = sum[i];
		sum[i] = sum[lenSum-i-1];
		sum[lenSum-i-1] = temp;
	}

	cout<<sum;
	return 0;
}