杭电OJ题 1753 大明A+B 解题报告

本文介绍了一种解决任意长度正小数加法问题的方法,通过C语言实现,能够处理多组测试数据,并输出最简形式的结果。代码中详细展示了如何进行小数点对齐、进位处理等关键步骤。

大明A+B

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5651    Accepted Submission(s): 1917


Problem Description
话说,经过了漫长的一个多月,小明已经成长了许多,所以他改了一个名字叫“大明”。
这时他已经不是那个只会做100以内加法的那个“小明”了,现在他甚至会任意长度的正小数的加法。

现在,给你两个正的小数A和B,你的任务是代表大明计算出A+B的值。
 

Input
本题目包含多组测试数据,请处理到文件结束。
每一组测试数据在一行里面包含两个长度不大于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
 

——————————————————————————————————————
注意小数点对齐,小细节注意,小心处理

/****************************
 *Name:大明A+B.c
 *Tags:ACM BigNumber
 *Note:注意细节处理
 ****************************/

#include <stdio.h>
#include <string.h>

int main()
{
      int d1, d2, l1, l2, i, c, l, j, point;
      char num1[500], num2[500], num[500];
      while(scanf("%s %s", num1, num2) != EOF) {
	    l1 = strlen(num1);
	    l2 = strlen(num2);
	    d1 = l1;  //初始化
	    d2 = l2;
	    for(i = 0; i < 500; i++) {
		  num[i] = '0';
	    }
	    for(i = 0; i < l1; i++) {
		  if(num1[i] == '.') {
			d1 = i;
			break;
		  }
	    }
	    for(i = 0; i < l2; i++) {
		  if(num2[i] == '.') {
			d2 = i;
			break;
		  }
	    }
	    if(d1 > d2) {
		  for(i = 0; i < l1; i++) {
			if(num1[i] == '.') {
			      num[i] = '.';
			} else {
			      num[i] = num1[i];
			}
		  }
		  if(d1 == l1) {
			num[d1] = '.';
		  } //如果输入的是整数,在最后填上小数点
		  c = 0;
		  for(i = d1+(l2-d2-1), j = l2-1; j > d2; j--, i--) {
			num[i] += (num2[j]-'0'+c);
			c = (num[i]-'0') / 10;
			num[i] = (num[i]-'0')%10 + '0';
		  }
		  for(i = d1-1, j = d2-1; j >= 0; i--, j--) {
			num[i] += (num2[j]-'0'+c);
			c = (num[i]-'0')/10;
			num[i] = (num[i]-'0')%10 + '0';
		  }
		  for(i = i; i >= 0; i--) {
			num[i] += c;
			c = (num[i]-'0')/10;
			num[i] = (num[i]-'0')%10 + '0';
		  } //当一个数的整数部分小于另一个的时候单独处理长的那个数的整数部分进位问题
		  point = d1;  //记录小数点的位置
	    } else {
		  for(i = 0; i < l2; i++) {
			if(num2[i] == '.') {
			      num[i] = '.';
			} else {
			      num[i] = num2[i];
			}
		  }
		  if(d2 == l2) {
			num[d2] = '.';
		  }
		  c = 0;
		  for(i = d2+(l1-d1-1), j = l1-1; j > d1; j--, i--) {
			num[i] += (num1[j]-'0'+c);
			c = (num[i]-'0') / 10;
			num[i] = (num[i]-'0')%10 + '0';
		  }
		  for(i = d2-1, j = d1-1; j >= 0; i--, j--) {
			num[i] += (num1[j]-'0'+c);
			c = (num[i]-'0')/10;
			num[i] = (num[i]-'0')%10 + '0';
		  }
		  for(i = i; i >= 0; i--) {
			num[i] += c;
			c = (num[i]-'0')/10;
			num[i] = (num[i]-'0')%10 + '0';
		  }  //当一个数的整数部分小于另一个的时候单独处理长的那个数的整数部分进位问题
		  point = d2;  //记录小数点的位置
	    }
	    for(i = 499; i > point; i--) {
		  if(num[i] != '0') {
			break;
		  } //去掉在小数部分最后面的0
	    }
	    if(i == point) {
		  i--;
	    } //如果小数部分都为0,去掉小数点
	    if(c) {
		  printf("%c", c+'0');
	    } //如果最后有进位,输出
	    for(j = 0; j <= i; j++) {
		  printf("%c", num[j]);
	    }
	    printf("\n");
      }
      return 0;
}		  


### 杭电OJ C++编程解与解决方案 杭电OJ是一个重要的编程技能提升平台,它提供了丰富的目资源,帮助学习者掌握基础算法、数据结构以及高级编程技术[^3]。以下是针对杭电OJ上常见的C++编程问及其解决方法的一些讨论。 #### 目类型分析 杭电OJ中的目通常涉及以下几个方面: 1. **基本控制流**:如`for`, `while`循环的应用。 2. **数组操作**:包括一维数组和二维数组的操作。 3. **字符串处理**:涉及到字符匹配、子串提取等问。 4. **数学逻辑**:利用数论知识解决问。 5. **指针应用**:深入理解内存管理机制。 6. **复杂数据结构**:链表、栈、队列等的实际运用。 下面给出几个具体的例子并附带相应的代码实现: #### 示例一:反转整数并与原数值比较 此问是关于如何逆向构建一个整数,并验证其特定条件下的性质。 ```cpp #include <iostream> using namespace std; // 定义函数用于计算给定数字a的反序形式 int reverseInt(int a){ int res = 0; while(a != 0){ res = res * 10 + a % 10; a /= 10; } return res; } int main(){ bool found = false; for(int i = 1000; i <= 1111; ++i){ if(reverseInt(i) == i * 9){ cout << i << endl; found = true; } } if(!found){ cout << "No such number exists." << endl; } } ``` 上述程序展示了如何遍历一定范围内的所有可能值,并检查它们满足某些特殊关系的能力[^1]。 #### 示例二:双指针法寻找符合条件的一对索引 当面对需要优化时间复杂度的任务时,“双指针”是一种非常有效的策略。 假设我们有一个未排序列表,目标是从其中找到两个元素使得它们之差等于指定常量k,则可以通过如下方式高效求解: ```cpp #include <vector> #include <algorithm> // sort function needed here. using namespace std; pair<int, int> findPairWithDifference(const vector<int>& nums, const int k){ pair<int,int> result(-1,-1); // Sort the array first to apply two pointer technique effectively. vector<int> sortedNums(nums); sort(sortedNums.begin(),sortedNums.end()); size_t left = 0 ; size_t right = 1 ; while( right < sortedNums.size()){ long diff = static_cast<long>(sortedNums[right]) - static_cast<long>(sortedNums[left]); if(diff == k ){ result.first=sortedNums[left]; result.second=sortedNums[right]; break; } if(diff<k )right++; else if(diff>k &&left<right-1)left++; else{ // To avoid infinite loop when both pointers are at same position and difference is zero or negative. right++; left++; } } return result; } ``` 这里采用了先排序再用双指针扫描的方法来快速定位合适的配对项[^5]。 #### 进一步探讨——环形链表检测及入口节点确定 对于更复杂的场景比如判定单链表是否存在闭环并且找出这个闭合点的位置,可以采用快慢指针的技术路线。 ```cpp struct ListNode { int val; ListNode *next; ListNode(int x):val(x), next(NULL){} }; ListNode* detectCycle(ListNode *head){ if(head==NULL || head->next==NULL)return NULL; ListNode *slow=head,*fast=head; do{ slow=slow->next; fast=(fast->next!=NULL)?fast->next->next:NULL; }while(fast&&slow!=fast); if(slow!=fast||!fast)return NULL;// No cycle detected. slow=head; while(slow!=fast){ slow=slow->next; fast=fast->next; } return slow; } ``` 这段代码实现了不仅能够确认是否含有环路而且还能准确定位到入环首结点的功能[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值