HDU1753 大明A+B【大数】

大明A+B

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


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
 

Author
linle
 

Source


问题链接HDU1753 大明A+B

问题简述:参见上文。

问题分析

  两个数可以能非常长,带有小数点,所以相加的话要么直接相加,要么转换为大数。大数的话,因为有小数点,就不那么好算了。所以还是直接相加。

程序说明

  直接相加也有两种计算方法,一种是把两个数读到字符串数组中,然后对齐小数点并且补0,再行相加;另外一种方法(本程序使用的方法)是直接计算位置,进行相加。

  读入数据时也有两种方法,一是用函数scanf()读入数据(字符串);二是使用函数getchar()读入数据(逐个字符读入)。由于进行相加时,需要计算小数点前后的位数,后一种可以一边读入数据一边计算。本程序采用后一种做法,逻辑上稍微复杂一些,需要更高的技巧。

  程序中,需要注意两点:

  1.计算结果的整数部分左边有可能有很多0;

  2.输入的最后一行,有可能没有换行("\n")文件就直接结束了,需要做特殊处理。


AC的C语言程序如下:

/* HDU1753 大明A+B */

#include <stdio.h>
#include <stdlib.h>

#define MAXN 400

char a[MAXN+1], b[MAXN+1], ans[MAXN+1];

int main(void)
{
    char c;
    int aleftcount, arightcount, bleftcount, brightcount, carry, count, i, j, k, l;

    for(;;) {
        c=getchar();
        if(c == EOF)
            break;

        // step1 读入A
        i = 0;
        aleftcount = 0;
        arightcount = 0;
        // setp1.1 读入A的小数点前的各位,并且位数计数
        while(c != '.' && c != ' ') {
            a[i++] = c;
            aleftcount++;
            c=getchar();
        }
        a[i++] = c; // 小数点或空格
        // step1.2 读入A的小数点后的各位,并且位数计数
        if(c != ' ')
            while((c=getchar()) != ' ') {
                a[i++] = c;
                arightcount++;
            }
        k = i - 1;

        // step2 读入B
        i = 0;
        bleftcount = 0;
        brightcount = 0;
        // setp2.1 读入B的小数点前的各位,并且位数计数
        while((c=getchar()) != '.' && c != '\n') {
            b[i++] = c;
            bleftcount++;
        }
        b[i++] = c; // 小数点或换行符
        // step2.2 读入B的小数点后的各位,并且位数计数
        if(c != '\n' && c != EOF)
            while((c=getchar()) != '\n' && c != EOF) {
                b[i++] = c;
                brightcount++;
            }
        l = i - 1;

        // step3 计算A+B
        // step3.1 小数部分相加
        j = 0;
        // step3.1.1 拷贝长的部分
        if(arightcount > brightcount) {
            count = arightcount - brightcount;
            while(count--)
                ans[j++] = a[k--];
        } else if(arightcount < brightcount) {
            count = brightcount - arightcount;
            while(count--)
                ans[j++] = b[l--];
        }
        // step3.1.2 同长部分相加
        carry = 0;
        count = (arightcount > brightcount) ? brightcount : arightcount;
        for(i=1; i<=count; i++) {
            ans[j] = carry + a[k] + b[l] - '0';
            if(ans[j] > '9') {
                ans[j] -= 10;
                carry = 1;
            } else
                carry = 0;
            j++;
            k--;
            l--;
        }
        // step3.2 小数点
        ans[j++] = '.';
        // step3.3 整数部分相加
        k--;
        l--;
        while(k >= 0 || l >= 0) {
            ans[j] = carry + ((k>=0) ? a[k] : '0') + ((l>=0) ? b[l] : '0') - '0';
            if(ans[j] > '9') {
                ans[j] -= 10;
                carry = 1;
            } else
                carry = 0;
            j++;
            k--;
            l--;
        }
        if(carry == 1)
            ans[j++] = '1';

        // step4 输出结果
        // step4.1 去掉右边的0和小数点
        k = 0;
        while(ans[k] == '0')
            k++;
        if(ans[k] == '.')
            k++;
        // step4.2 输出结果
        for(i=j-1; i>=k; i--)
            putchar(ans[i]);
        putchar('\n');
    }

    return 0;
}


  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值