带小数的高精度加减法运算(C++)

题目如下:

带小数的高精度加减法运算(C++)_第1张图片带小数的高精度加减法运算(C++)_第2张图片

输入数据:
4
+
1,111,111,111,111,111,111,111,111,111,111,111,111
222,222,222,222,222,222,222,222,222,222,222,222
+
-12,345,678,901,234,567,890,123,456,789,012,345,678,901,234,567,890
98,765,432,198,765,432,198,765,432,198,765,432,198,765,432,198,765
+
3.14159265358979384626
6.66666666666666666666666
-
-41,829,471,284,124,414.49104801248981284
-64,580,569,452,374,277.12783183148912947

输出数据:

1,333,333,333,333,333,333,333,333,333,333,333,333
86,419,753,297,530,864,308,641,975,409,753,086,519,864,197,630,875
9.80825932025646051292666
22,751,098,168,249,862.63678381899931663

代码如下(含一些注释):

#include
#include
#include
using namespace std;
/*
大致思路是
先将字符串转化成两个正数相加减的模型(去符号)
然后将字符串变为int型存储起来,‘.’间隔出两部分
最后分别对小数部分和整数部分操作,作+-运算
*/
void qufuhao(char s[])
{
	int len = strlen(s);
	for (int i = 1;i < len;i++)
	{
		s[i - 1] = s[i];
	}
	s[len-1] = '\0';
}

void qudouhao(char s[])
{
	int len = 0;
	for (int i = 0;i < strlen(s);i++)
	{
		if (s[i] != ',')
		{
			s[len++] = s[i];
        }
	}
	s[len] = '\0';
}

void save(char s1[], int A[], int &diana, int a[], int &xa)
{
	for (int i = 0;i < strlen(s1);i++)
	{
		if (s1[i] == '.')
		{
			diana = i;
			break;
		}
		A[i] = s1[i] - '0';//记录整数部分,并逆序存储
	}
	if (diana)//若有小数部分
	{
		for (int i = diana + 1;i < strlen(s1);i++)
		{
			a[xa++] = s1[i] - '0';//记录小数部分
		}
	}
	else//若无小数部分(无小数点)
	{
		diana = strlen(s1);
	}
	reverse(A, A + diana);
}

int comp(int A[], int diana, int a[], int xa, int B[], int dianb, int b[], int xb)
{
	if (diana > dianb)
		return 1;
	else if (diana < dianb)
		return -1;
	else//整数部分一样长
	{
		for (int i = diana - 1;i >= 0;i--)
		{
			if (A[i] > B[i])
				return 1;
			else if (A[i] < B[i])
				return -1;
		}//整数部分都相同,继续比较小数部分
		int lenx = xa > xb ? xa : xb;
		for (int i = 0;i < lenx;i++)
		{
			if (a[i] > b[i])
				return 1;
			else if (a[i] < b[i])
				return -1;
		}
		return 0;
	}
}

//a-b(大-小)
void subtract(int A[], int diana, int a[], int xa, int B[], int dianb, int b[], int xb,int C[],int c[])
{
	int jie = 0;//借位
	int lenz = diana > dianb ? diana : dianb;
	int lenx = xa > xb ? xa : xb;
	for (int i = lenx - 1;i >= 0;i--)
	{
		c[i] = a[i] - b[i] - jie;
		if (c[i] < 0)
		{
			c[i] += 10;
			jie = 1;
		}
		else
		{
			jie = 0;
		}
	}
	for (int i = 0;i < lenz;i++)
	{
		C[i] = A[i] - B[i] - jie;
		if (C[i] < 0)
		{
			C[i] += 10;
			jie = 1;
		}
		else
		{
			jie = 0;
		}
	}
}

void output(int C[], int lenz, int c[], int lenx, int sig)
{
	//去小数尾零
	int len = lenx;
	for (int i = len - 1;i >= 0;i--)
	{
		if (c[i] == 0)
		{
			lenx--;
		}
		else
		{
			break;
		}
	}
	//去前导零
	while (lenz > 0 && C[lenz - 1] == 0)
	{
		lenz--;
	}
	if (lenz == 0)//若整数部分全为0
	{
		if (lenx == 0)//若小数部分也全为0
		{
			cout << '0';
		}
		else
		{
			if (sig == -1)
			{
				cout << '-';
			}
			cout << '0' << '.';
			for (int i = 0;i < lenx;i++)
			{
				cout << c[i];
			}
		}
	}
	else
	{
		if (sig == -1)
			cout << '-';
		for (int i = lenz - 1;i >= 0;i--)
		{
			cout << C[i];
			if (i % 3 == 0 && i)
				cout << ',';
		}
		if (lenx != 0)
		{
			cout << '.';
			for (int i = 0;i < lenx;i++)
			{
				cout << c[i];
			}
		}
	}
	cout << endl;
}

int main()
{
	int n;
	cout << "输入组数:";
	cin >> n;
	for (int i = 0;i < n;i++)
	{
		cout << endl;
		char s1[260] = { 0 }, s2[260] = { 0 }, k;
		cout << "请输入+或-号:";
		cin >> k;
		cout << "第一个数:";
		cin >> s1;
		cout << "第二个数:";
		cin >> s2;
		cout << "结果为:";
		int sig = 1;
		//去符号,转化成两个正数加减的模型
		switch (k)
		{
		case '+':
		{
			if (s1[0] == '-' && s2[0] != '-')
			{
				k = '-';sig = -1;qufuhao(s1);
			}
			if (s1[0] != '-' && s2[0] == '-')
			{
				k = '-';qufuhao(s2);
			}
			if (s1[0] == '-' && s2[0] == '-')
			{
				sig = -1;qufuhao(s1);qufuhao(s2);
			}
		}
		break;
		case '-':
		{
			if (s1[0] == '-' && s2[0] != '-')
			{
				k = '+';sig = -1;qufuhao(s1);
			}
			if (s1[0] != '-' && s2[0] == '-')
			{
				k = '+';qufuhao(s2);
			}
			if (s1[0] == '-' && s2[0] == '-')
			{
				sig = -1;qufuhao(s1);qufuhao(s2);
			}
		}
		}

		//去逗号,然后整数部分和小数部分分开存储
		qudouhao(s1);qudouhao(s2);
		int A[260] = { 0 }, diana = 0, a[260] = { 0 }, xa = 0;//整数部分的长度刚好为小数点的下标
		int B[260] = { 0 }, dianb = 0, b[260] = { 0 }, xb = 0;
		int C[260] = { 0 }, lenz = 0, c[260] = { 0 }, lenx = 0;
		save(s1, A, diana, a, xa);
		save(s2, B, dianb, b, xb);
		lenz = diana > dianb ? diana : dianb;//初始结果的整数部分长
		lenx = xa > xb ? xa : xb;//初始结果的小数部分长

		//分加减法计算
		switch (k)
		{
		case'+':
		{
			int jin = 0;
			//小数部分相加
			for (int i = lenx - 1;i >= 0;i--)
			{
				c[i] = a[i] + b[i] + jin;
				if (c[i] > 9)
				{
					c[i] -= 10;
					jin = 1;
				}
				else
				{
					jin = 0;
				}
			}
			//整数部分相加
			for (int i = 0;i < lenz;i++)
			{
				C[i] = A[i] + B[i] + jin;
				if (C[i] > 9)
				{
					C[i] -= 10;
					jin = 1;
				}
				else
				{
					jin = 0;
				}
			}
			output(C, lenz, c, lenx, sig);
		}
		break;
		case'-':
		{
			int t = comp(A, diana, a, xa, B, dianb, b, xb);
			if (t == 1)//a-b
			{
				subtract(A, diana, a, xa, B, dianb, b, xb, C, c);
				output(C, lenz, c, lenx, sig);
			}
			else if (t == -1)//-(a-b)
			{
				sig = -sig;
				subtract(B, dianb, b, xb, A, diana, a, xa, C, c);
				output(C, lenz, c, lenx, sig);
			}
			else
			{
				cout << '0' << endl;
			}
		}
		}
	}
	return 0;
}

你可能感兴趣的:(刷题录,c++,算法,数据结构)