算法笔记练习 5.6 大整数运算 问题 C: 浮点数加法

算法笔记练习 题解合集

题目链接

题目

题目描述
求2个浮点数相加的和
题目中输入输出中出现浮点数都有如下的形式:
P1P2…Pi.Q1Q2…Qj
对于整数部分,P1P2…Pi是一个非负整数
对于小数部分,Qj不等于0

输入
对于每组案例,第1行是测试数据的组数n,每组测试数据占2行,分别是两个加数。
每组测试数据之间有一个空行,每行数据不超过100个字符

输出
每组案例是n行,每组测试数据有一行输出是相应的和。
输出保证一定是一个小数部分不为0的浮点数

样例输入

2
3.756
90.564

4543.5435
43.25

样例输出

94.32
4586.7935

思路

由于比较抽象,在每一个步骤下面以1.863.14159相加来举例说明,请搭配例子食用


步骤:

  1. 首先获得bign类型的iafaibfb,分别表示第一个数的整数部分,小数部分,第二个数的整数部分,小数部分;
    (例:输入1.863.14159,则有ia = 1fa = 86ib = 3fb = 14159
  2. ians = ia + ib
    (例:ians=ia + ib=1 + 3=4
  3. 对于fafb,把长度较短的那个后面加零对齐;
    (例:这里fa比较短,因为fb有五位,所以把fa加长到86000
  4. fans = fa + fb,此处分为最高位有进位和无进位两种情况:
    a. 无进位,比较理想的情况,无需特殊处理;
    b. 有进位,首先ians要加1,其次fans的最高位上的1要被抹去;
    (例:fans=fa + fb=86000 + 14159=100159,最高位有进位,那么首先ians要变成5,其次fans要变成00159
  5. 删去fans末尾所有连续的0
    (例:这个例子中的fans没有问题,但假设到这一步fans003405000,要修改为003405
  6. 输出ians+.+fan
    (例:即5.00159

代码

#include 
#include 

#define MAX 2000

struct bign {
	int d[MAX];
	int len;
	bign() {
		memset(d, 0, sizeof(d));
		len = 0; 
	} 
};

bign change(char *str) {
	bign a;
	a.len = strlen(str);
	for (int i = 0; i != a.len; ++i)
		a.d[i] = str[a.len - i - 1] - '0'; 
	return a;
} 

// 高进度加法,若最高位有进位,carry 变为 1 
bign add(bign a, bign b, int &carry) {
	bign c;
	carry = 0;
	int len = (a.len > b.len) ? a.len : b.len;
	for (int i = 0; i != len; ++i) {
		int temp = a.d[i] + b.d[i] + carry;
		c.d[c.len++] = temp % 10;
		carry = temp / 10; 
	}
	if (carry)
		c.d[c.len++] = carry;
	return c;
}

void print(bign a) {
	for (int i = 0; i != a.len; ++i)
		putchar(a.d[a.len-i-1] + '0');
} 

int main() {
	int n;
	char s1[MAX], s2[MAX], s3[MAX], s4[MAX];  // 分别为 a、b 的整数、小数部分 
	while (scanf("%d", &n) != EOF) {
		while (n--) {
			char input[MAX];
			char *p1 = s1, *p2 = s2, *p3 = s3, *p4 = s4;
			scanf("%s", input);
			int pointFlag = 0;
			for(int i = 0; i != strlen(input); ++i){
				if (input[i] == '.') {
					pointFlag = 1;
					continue;
				} 
				if (pointFlag)
					*p2++ = input[i];
				else
					*p1++ = input[i];
			} 
			*p1 = '\0';
			*p2 = '\0';
			scanf("%s", input);
			pointFlag = 0;
			for(int i = 0; i != strlen(input); ++i){
				if (input[i] == '.') {
					pointFlag = 1;
					continue;
				} 
				if (pointFlag)
					*p4++ = input[i];
				else
					*p3++ = input[i];
			}
			*p3 = '\0';
			*p4 = '\0';
			// 把读入的字符串转换成 bign 
			bign ia = change(s1);
			bign fa = change(s2);
			bign ib = change(s3);
			bign fb = change(s4);
			// 开始加法 
			int carry;
			bign ians = add(ia, ib, carry);		// 整数部分直接相加 
			// 小数部分加法 
			if (fa.len < fb.len) {	// 保证 fa 的长度不小于 fb 
				bign temp = fa;
				fa = fb;
				fb = temp;
			} 
			if (fa.len > fb.len) {	// 如果长度不一样,在 fb 后面补 0,以便相加 
				int offset = fa.len - fb.len;
				memmove(fb.d + offset, fb.d, fb.len * sizeof(int));
				memset(fb.d, 0, offset * sizeof(int));
				fb.len = fa.len;
			}
			bign fans = add(fa, fb, carry);
			// 如果小数部分有进位,让整数部分加一,抹去小数部分最高位 
			if (carry) {
				bign one;
				one.len = 1;
				one.d[0] = 1; 
				ians = add(ians, one, carry);
				fans.d[fans.len--] = 0; 
			}
			// 删掉所有小数部分低位的 0 
			int offset = 0;
			for ( ; offset != fans.len; ++offset) 
				if (fans.d[offset] != 0)
					break;
			memmove(fans.d, fans.d + offset, (fans.len - offset) * sizeof(int));
			fans.len -= offset; 
			// 输出 ians, fans
			print(ians); 
			putchar('.');
			print(fans); 
			putchar('\n'); 
		} 
	} 
	return 0;
} 

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