描述
acmj最近发现在使用计算器计算高精度的大数加法时很不方便,于是他想着能不能写个程序把这个问题给解决了。
-
输入
-
包含多组测试数据
每组数据包含两个正数A,B(可能为小数且位数不大于400)
输出
- 每组输出数据占一行,输出A+B的结果,结果需要是最简的形式。 样例输入
-
1.9 0.1 0.1 0.9 1.23 2.1 3 4.0
样例输出
-
2 1 3.33 7
做这个题的时候WA了很多次,还是因为问题考虑的不全面。
比如下面几组数据:0.0+1.2 999+1 (考虑整数的直接进位) 0.98+0.10 1+1 9+0.1 0.1+9(考虑一个浮点数加一个整数的情况)
我的方法比较繁琐……
定义四个数组分别存两个运算数,得数的整数部分和小数部分。
其中整数部分数字要倒着存储,0001000 1后面的0要输出, 1前面的0不输出。
小数部分数字要正着存储,因为0.0000100 这种情况下,1前面的0还是要输出 倒着存不会输出1之前的0,1后面的0可以控制不输出
函数add1 用于计算整数部分 add2计算小数部分,如果小数部分向整数部分有进位,调用add3函数。
如果一个数是整数一个数是浮点数,那么直接把两数字的整数部分相加,小数部分直接取浮点数的小数部分。
输出的时候要从第一个不是0的数开始输出。
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define SIZE 1000
int c[SIZE * 2];//存储整数部分
int d[SIZE * 2];//存储小数部分
void add1(char a[], char b[], int m, int n)
{//整数部分相加
int a1[SIZE], b1[SIZE];
memset(a1, 0, sizeof(a1));
memset(b1, 0, sizeof(b1));
int i, j, k, max;
max = m > n ? m : n;
for(i = 0, j = m - 1; i < m; i++, j--)
{
a1[i] = a[j] - '0';
}
for(i = 0, j = n - 1; i < n; i++, j--)
{
b1[i] = b[j] - '0';
}
for(i = 0, k = 0; i < max; i++)
{
c[i] = (a1[i] + b1[i] + k) % 10;
}
if(k != 0)
c[i] = k;
}
int add2 (char a[], char b[], int m, int n)
{//小数部分相加
int i, j, k, f, l;
int t1 = strlen(a);
int t2 = strlen(b);
//小数部分位数要相同,位数少的在后面补0
for(i = m + 1; a[i] != '\0'; i++)
{}
for(j = n + 1; b[j] != '\0'; j++)
{}
f = i > j ? i : j;
int max = (t1 - m - 1) > (t2 - n - 1) ? (t1 - m - 1) : (t2 - n - 1);
if((t1 - m - 1) > (t2 - n - 1))
{
int t = (t1 - m - 1) - (t2 - n - 1);
while (t--)
{//补0操作
b[j++] = '0';
}
b[j++] = '\0';
}
if((t1 - m - 1) < (t2 - n - 1))
{
int t = (t2 - n - 1) - (t1 - m - 1);
while (t--)
{//补0操作
a[i++] = '0';
}
a[i++] = '\0';
}
for(l = max - 1, i = m + max, j = n + max, k = 0; l >= 0; i--, j--, l--)
{
d[l] = ((a[i] - '0') + (b[j] - '0') + k) % 10;
k = ((a[i] - '0') + (b[j] - '0') + k) / 10;
}
return k;
}
void add3 (int k)
{//小数向整数进位相加
int i, n;
c[0] += k;
for(i = 1, n = 0; i < SIZE * 2 - 1; i++)
{
c[i] += c[i - 1] / 10;
c[i - 1] %= 10;
}
}
int main (void)
{
int i, j, len1, len2, k1, k2, l, m;
char a[SIZE], b[SIZE];
while (1)
{
k1 = 0, k2 = 0;
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
memset(c, 0, sizeof(c));
memset(d, 0, sizeof(d));
scanf("%s%s", a, b);
if(!isdigit(a[0]))
return 0;
len1 = strlen(a);
for(i = 0; i < len1; i++)
{
if(a[i] == '.')
break;
}
len2 = strlen(b);
for(j = 0; j < len2; j++)
{
if(b[j] == '.')
break;
}
/*如果有小数部分*/
//如果两个数都有小数部分
if(i != len1 && j != len2)
{
k2 = add2(a, b, i, j);
}
//两个数中如果只有一个数有小数部分,直接把有小数部分搬到d数组中就可以
if(i == len1 && j != len2)
{
for(m = 0, l = j + 1; b[l] != '\0'; m++, l++)
d[m] = b[l] - '0';
}
if(i != len1 && j == len2)
{
for(m = 0, l = i + 1; a[l] != '\0'; m++, l++)
d[m] = a[l] - '0';
}
//算整数部分
add1(a, b, i, j);
//如果小数有进位
if(k2 != 0)
add3(k2);
//输出整数
i = SIZE * 2 - 1;
while(c[i] == 0 && i > 0)
{
i--;
}
for(; i >= 0; i--)
printf("%d", c[i]);
//输出小数
i = SIZE * 2 - 1;
while (d[i] == 0 && i >= 0)
{
i--;
}
//printf("\ni = %d\n", i);
if(i != -1)
{
printf(".");
for(j = 0; j <= i; j++)
printf("%d",d[j]);
}
printf("\n");
}
return 0;
}