话说,经过了漫长的一个多月,小明已经成长了许多,所以他改了一个名字叫“大明”。
这时他已经不是那个只会做100以内加法的那个“小明”了,现在他甚至会任意长度的正小数的加法。
现在,给你两个正的小数A和B,你的任务是代表大明计算出A+B的值。
这时他已经不是那个只会做100以内加法的那个“小明”了,现在他甚至会任意长度的正小数的加法。
现在,给你两个正的小数A和B,你的任务是代表大明计算出A+B的值。
Input
本题目包含多组测试数据,请处理到文件结束。
每一组测试数据在一行里面包含两个长度不大于400的正小数A和B。
每一组测试数据在一行里面包含两个长度不大于400的正小数A和B。
Output
请在一行里面输出输出A+B的值,请输出最简形式。详细要求请见Sample Output。
Sample Input
1.1 2.9 1.1111111111 2.3444323343 1 1.1
Sample Output
4 3.4555434454 2.1
代码:
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 810; //两数长度不大于400.
char a[N], b[N];
int c[N], d[N];
int main()
{
int flag1, flag2, len1, len2, pos;
int up, top, down;
int i,k;
while(scanf("%s %s", a, b) != EOF)
{
flag1 = flag2 = -1;
memset(c, 0, sizeof(c));
memset(d, 0, sizeof(d));
len1 = strlen(a);
len2 = strlen(b);
for( i = 0; i < len1; ++i) //判断第一个数的整数部分长度flag1、小数部分的长度( len1 - flag1-1)
if(a[i] == '.')
flag1 = i;
for( i = 0; i < len2; ++i) //判断第二个数的整数部分长度flag2、小数部分的长度( len2 - flag2-1)
if(b[i] == '.')
flag2 = i;
if(flag1 == - 1 && flag2 == -1) //2个数都是整数 字符加法运算
{
for( i = len1 - 1, k = 0; i >= 0; --i)
c[k++] = a[i] - '0';
for( i = len2 - 1, k = 0; i >= 0; --i)
d[k++] = b[i] - '0';
for( i = 0, up = 0; i < N; ++i)
{
c[i] = c[i] + d[i] + up;
up = c[i] / 10;
c[i] %= 10;
}
for(top = N -1; !c[top] && top >= 0; --top);//去掉前导0.
if(top < 0)
{
printf("0\n");
continue;
}
for( i = top; i >= 0; --i)
printf("%d", c[i]);
printf("\n");
}
else if(flag1 != -1 && flag2 != -1) //二数都是小数
{
if(len1 - 1 - flag1 > len2 - 1 - flag2) //a的小数部分比b的长
{
for( i = 0; i < len1 - len2 + flag2 - flag1; ++i)
b[len2 + i] = '0';
b[len1 + flag2 - flag1 + 1] = '\0';
len2 += len1 - len2 + flag2 - flag1;
}
else if((len1 - 1 - flag1 < len2 - 1 - flag2))
{
for( i = 0; i < len2 - len1 + flag1 - flag2; ++i)
a[len1 + i] = '0';
a[len2 + flag1 - flag2 + 1] = '\0';
len1 += len2 - len1 + flag1 - flag2; //结果长度len1.
}
pos = 0;
for( i = len1 - 1; i >= 0; --i)
if(a[i] != '.')
pos++;
else
break;
for( i = len1 - 1, k = 0; i >= 0; --i)
if(a[i] != '.')
c[k++] = a[i] - '0';
for( i = len2 - 1, k = 0; i >= 0; --i)
if(b[i] != '.')
d[k++] = b[i] - '0';
for( i = 0, up = 0; i < N; ++i)
{
c[i] = c[i] + d[i] + up;
up = c[i] / 10;
c[i] = c[i] % 10;
}
for( i = 0; i < N; ++i)
a[i] = c[i] + '0'; //把字符c[]转化成数字a[],放结果
for(top = N - 1; a[top] == '0'; --top); //去掉前导0
if(top < 0)
{
printf("0\n");
continue;
}
for(down = 0; a[down] == '0' && down < pos; ++down); //去掉后导0
for( i = top; i >= down; --i)
if(i == pos && down != pos) //判断是否输出小数点
printf("%c.", a[i]);
else
printf("%c", a[i]);
printf("\n");
}
else //当有一个是整数,一个是小数时。
{
if(flag1 == -1) //当b是小数,a是整数时
{
for( i = len1 - 1, k = 0; i >= 0; --i)
c[k++] = a[i] - '0';
for( i = flag2 - 1, k = 0; i >= 0; --i)
d[k++] = b[i] - '0';
for( i = 0, up = 0; i < N; ++i)
{
c[i] = c[i] + d[i] + up;
up = c[i] / 10;
c[i] %= 10;
}
for(top = N - 1; !c[top]; --top); //去前导0
if(top < 0)
{
printf("0\n");
continue;
}
for(down = len2 - 1; b[down] == '0'; --down); //去后导0
for( i = top; i >= 0; --i)
printf("%d", c[i]);
if(b[down] != '.')
for( i = flag2; i <= down; ++i)
printf("%c", b[i]);
printf("\n");
}
else //a是小数,b是整数时
{
for( i = flag1 - 1, k = 0; i >= 0; --i)
c[k++] = a[i] - '0';
for( i = len2 - 1, k = 0; i >= 0; --i)
d[k++] = b[i] - '0';
for( i = 0, up = 0; i < N; ++i)
{
c[i] = c[i] + d[i] + up;
up = c[i] / 10;
c[i] %= 10;
}
for(top = N - 1; !c[top]; --top); //去前导0
if(top < 0)
{
printf("0\n");
continue;
}
for(down = len1 - 1; a[down] == '0'; --down); //去后导0
for( i = top; i >= 0; --i)
printf("%d", c[i]);
if(a[down] != '.')
for( i = flag1; i <= down; ++i)
printf("%c", a[i]);
printf("\n");
}
}
}
return 0;
}
思路解析:
小数相加,有三种情况,两个都是整数,两个都是小数,一整数一小数。
这三种情况都要单独处理,而且保证结果没有多余的前导“0”和后导“0”。
可以把这三种情况,都当做是两小数相加,结果输出时,判断是否有小数即可。
想法很好,实现过程很艰辛。。。努力!!!