注册 登录
编程论坛 C语言论坛

任意长度的正小数的加法 求助

Sky_ 发布于 2020-01-06 18:56, 4693 次点击
任意长度的正小数的加法
给你两个正的小数A和B,你的任务是计算出A+B的值
输入
本题目包含多组测试数据,请处理到文件结束。
每一组测试数据在一行里面包含两个长度不大于400的正小数A和B
输出
请在一行里面输出输出A+B的值,请输出最简形式。
样例输入
1.1 2.9
1.1111111111 2.3444323343
1 1.1
样例输出
4
3.4555434454
2.1
我想着想着就把自己绕晕了 有没有简洁的代码可以参考一下
19 回复
#2
纯蓝之刃2020-01-06 19:16
程序代码:
#include<stdio.h>

int main()
{
    int i=0,n;
    float a,b,sum[100];
    printf("请输入数据组数:");
    scanf("%d",&n);
    printf("请输入数据:\n");
    for(i=0;i<n;i++)
    {
        scanf("%f %f",&a,&b);
        sum[i]=a+b;
    }

    for(i=0;i<n;i++)
        printf("%f\n",sum[i]);

    return 0;
}
#3
rjsp2020-01-07 08:59
题目本身是很简单的,但就怕题目作者故意加入一些无聊的陷阱。
比如会不会有不是小数的输入?如:123 .123
比如会不会有前后零?如:0001.2 2.30000
比如小于1时整数部分要不要零?.1 .2 是输出 .3 还是 0.3
#4
forever742020-01-07 09:46
嗯,样例输入第三行就有个整数1,不带点的
#5
rjsp2020-01-07 11:08
回复 4楼 forever74
所以不喜欢这类的题目

程序代码:
#include <stdio.h>
#include <string.h>

void bar( const char* restrict s, char p[restrict static 1000] )
{
    size_t len = strlen( s );
    const char* dot = strchr( s, '.' );

    memset( p, '0', 1000 );
    p[499] = '.';
    p[999] = '\0';
    memcpy( dot?p+499-(dot-s):p+499-len, s, len );
}

void foo( const char* a, const char* b )
{
    char a_[1000], b_[1000], c_[1000];
    bar( a, a_ );
    bar( b, b_ );
    bar( "", c_ );

    // 相加
    unsigned carry = 0;
    for( size_t i=998; i!=0; --i )
    {
        if( i != 499 )
        {
            carry += a_[i]-'0' + b_[i]-'0';
            c_[i] = carry%10 + '0';
            carry /= 10;
        }
    }

    // 去除尾部的零
    {
        size_t i;
        for( i=998; c_[i]=='0'; --i );
        c_[i+(c_[i]!='.')] = '\0';
    }

    // 去除首部的零
    char* p = c_ + strspn(c_,"0");
    p -= (*p=='.');

    puts( p );
}

int main( void )
{
    for( char a[401],b[401]; scanf("%s%s",a,b)==2; )
        foo( a, b );
}

#6
forever742020-01-07 21:44
r版您的版本太新,新到脱离我这种群众了。还得重新学习才能看懂俺就
#7
xianfajushi2020-01-08 09:37
觉得没必要去理会0的存在,就没必要去做特别对0的处理.
#8
xianfajushi2020-01-08 09:38
其实很简单的程序,只是不知为何,老大地不愿动这手.
#9
xianfajushi2020-01-08 17:01
在任何论坛中我遇到的‘还珠格格’的小兔最多了,因此,在此陈述一下不用处理0的想法,我的构思就是要想法对齐小数点位置,这样就不用理会虾米0的存在,函数原型void 字符四则运算之加法(char* a,char* aa);
‘还珠格格’的小兔,小兔吃虾米?萝卜,还珠格格上课第一天...哈哈
或许有天兴起,会花点精力与时间实现我的构思写写。

[此贴子已经被作者于2020-1-8 19:41编辑过]

#10
叶纤2020-01-08 17:12
回复 9楼 xianfajushi
额→_→这题真不简单,我居然头脑简单滴想成两数相加就行了1.11111111257558555+226665.22585555还要显示相同位数 ,,额→_→鄙视我之前说这就是最简单的加减运算

[此贴子已经被作者于2020-1-8 17:51编辑过]

#11
forever742020-01-08 19:27
程序代码:

#include <stdio.h>
#include <string.h>
void foo()
{
    char a[401] = { 0 }, b[401] = { 0 }; //字符形式,不用的位置统统是0
    char sumint[810] = { 0 }, sumdec[810] = { 0 };  //每一位都是数值形式,不是字符。前者倒排
    int pa=-1, pb=-1, len_a, len_b;
    int i, td;
    scanf("%s %s", a, b);
    len_a = strlen(a);
    len_b = strlen(b);
    for (i = 0; i < 401; i++)
    {   //找到小数点
        if (a[i] == '.' || !a[i] && pa == -1)pa = i; //万一输入没有点
        if (b[i] == '.' || !b[i] && pb == -1)pb = i;
        if (pa >=0 && pb >= 0)break;
    }
    for (td = i = (len_a - pa > len_b - pb) ? len_a - pa : len_b - pb; i > 0; i--)
    {   //小数部分从低到高按位求和,前面多出一位保存给整数部分的进位,td保存了用得到的最大下标
        sumdec[i] += (a[pa + i] ? a[pa + i] - 48 : 0) + (b[pb + i] ? b[pb + i] - 48 : 0);
        sumdec[i - 1] = sumdec[i] / 10;
        sumdec[i] %= 10;
    }
    while (td > 0 && !sumdec[td])td--; //抹掉后缀0
    sumint[0] = sumdec[0]; //进位
    for (i = 1; pa - i >= 0 || pb - i >= 0; i++)
    {   //整数部分从低到高按位求和
        sumint[i - 1] += (pa - i >= 0 ? a[pa - i] - 48 : 0) + (pb - i >= 0 ? b[pb - i] - 48 : 0);
        sumint[i] = sumint[i - 1] / 10;
        sumint[i - 1] %= 10;
    }
    while (i > 0 && !sumint[i])i--; //抹掉前置0
    for (; i >= 0; i--) //因为倒排,所以倒输出
        printf("%d", sumint[i]);
    if(td > 0)putchar('.'); //小数部分为零就没有小数点了
    for (i = 1; i < td + 1; i++) //输出小数部分,sumdec[0]是进位信息,所以从下标1开始
        printf("%d", sumdec[i]);
    putchar('\n');
}
#12
xianfajushi2020-01-08 19:38
依你的意思该怎么写这题程序?
以下是引用叶纤在2020-1-8 17:12:57的发言:

额→_→这题真不简单,我居然头脑简单滴想成两数相加就行了1.11111111257558555+226665.22585555还要显示相同位数 ,,额→_→鄙视我之前说这就是最简单的加减运算

#13
叶纤2020-01-08 21:26
回复 12楼 xianfajushi
大佬的灵魂发问是个奇妙的东西,会让你不由自主的拿起手机编译起来。。。。
先说问题,1,for循环不连续2,400位的小数我这个实现不了,3我是照着我几天前突然看到的头文件库加强着写的,有很多英文我没看懂,后期再啃。4我是用C++写的。。。。
#include <limits>
#include <iomanip>
#include <iostream>
int main()
{
for(int i=0;i<3;i++){
    double value1 ;
    double value2 ;
    double value3;
    std::cin>>value1>>value2;
    value3=value1+value2;
    constexpr auto digits1 = std::numeric_limits<decltype(value1)>::digits10;
   constexpr auto max_digits101 = (std::numeric_limits<decltype(value1)>::max_digits10)-1;
    //显示类型的位数比如double最大15-17位
 
constexpr auto digits2 = std::numeric_limits<decltype(value2)>::digits10;
   constexpr auto max_digits102 = (std::numeric_limits<decltype(value2)>::max_digits10)-1;
  
 
constexpr auto digits3 = std::numeric_limits<decltype(value3)>::digits10;
   constexpr auto max_digits103 = (std::numeric_limits<decltype(value3)>::max_digits10)-1;

    const auto original_precision = std::cout.precision();
   
        std::cout
            << std::setprecision(max_digits103) << value3 << '\n';
    return 0;
}
}
5后期测试
只有本站会员才能查看附件,请 登录
只有本站会员才能查看附件,请 登录
只有本站会员才能查看附件,请 登录
分别测试了几种数据
#14
叶纤2020-01-08 21:28
回复 12楼 xianfajushi
我的思维就就是c=a+b很简单的
#15
forever742020-01-08 22:40
你要是引用一个大数库,剩下的可不就是c=a+b么。
#16
叶纤2020-01-09 00:43
回复 15楼 forever74
谢谢指点
#17
lin51616782020-01-15 15:59
题目简单 但各位的处理实在是太嘈杂了
简单的格式化处理而已
各种找到小数点 补全 什么的 都是多余的
%[^.].%s
按照小数点分割读取2个字符串
然后 整数部分相加 小数部分相加
输出 整数 输出. 输出小数 完事
#18
bcbbcclbbc2020-01-16 22:29
今天想吃鱼,一是让市集老板给你处理好切块带回家,二是自己买鱼处理内脏血污后回家自个处理,看各自手艺。鱼处理好了,还需要煎炒煮炖外加调味,方可入胃,最后一个“吃”字,简单不?
#19
xianfajushi2020-01-17 16:36
今天摆渡了一下大数阶乘,其中思路就不错https://baike.baidu.com/item/%E9%98%B6%E4%B9%98/4437932?fr=aladdin 最后一个C程序5000位的
#20
lin51616782020-01-17 17:52
提示: 该帖被管理员或版主屏蔽,只有管理员可见
1