bol_in 2022-06-06 00:31 采纳率: 64.6%
浏览 40
已结题

35 - 長浮點數小數運算 以陣列實做長浮點小數的運算,計算並輸出兩數的相加、相減、相乘 輸出的兩個部分長度最大精確各為 60 位

長浮點數小數運算

以陣列實做長浮點小數的運算,計算並輸出兩數的相加、相減、相乘
輸出的兩個部分長度最大精確各為 60 位


輸入說明:
輸入2行,代表兩個浮點小數

輸出說明:
輸出 3 行
第1行為兩數相加之結果
第2行為兩數相減之結果
第3行為兩數相乘之結果


Sample Input 1:
54375594968196412353419.7136567768967814548988
73287424855639561252347.4564956732129084076487

Sample Output 1:
127663019823835973605767.1701524501096898625475
-18911829887443148898927.7428388963161269527499 3985047330212387208846838718241110977261606713.61406369102666397315364414705498798400445156


Sample Input 2:
-9234507190321346790456789.1931587893642640223756
-9234507190321346790456789.1931587893642640223756

Sample Output 2:
-18469014380642693580913578.3863175787285280447512
0
85276123048096654594016550136815157974048477583569.58751391797434997190616787629405161746747536


Sample Input 3:
-26867969463606565474768123.5645144634542221
136452564856366342453.724563547586473564776

Sample Output 3:
-26867833011041709108425669.839950915867748535224
-26868105916171421841110577.289078011040695664776
-3666203345791645284973102086942259202952614005.2383003686028975820993973094750407496


Sample Input 4:
19342748593927235.4859695323773685960483721
-939329384736226582829496.04837462845050055

Sample Output 4:
-939329365393477988902260.5624050960731319539516279
939329404078975176756731.5343441608278691460483721 -18169212135841181949695789552712699214732.353525637433292855735431230415598257654655

  • 写回答

2条回答 默认 最新

  • 关注

    (1)读取两个字符串后,根据小数点位置,对齐两个字符串,不足位用0补齐
    (2)从低位开始计算加、减、乘,并依次累加存储如结果阵列
    (3)去掉结果阵列首尾的0
    用测试用例2进行了测试,结果如下:

    img

    代码:

    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    
    
    #define MAXNUM (int)60
    
    //去除前面的0
    void deletePreZero(char c[])
    {
        int i;
        while (c[0] == '0')
        {
            for (i = 0; i < strlen(c) - 1; i++)
                c[i] = c[i + 1];
            c[strlen(c) - 1] = 0;
        }
    }
    //去除后面的0
    void deleteBackZero(char c[])
    {
        int i = strlen(c) - 1;
        while (c[i] == '0')
        {
            c[i] = 0;
            i = strlen(c) - 1;
        }
    }
    
    
    //小数点对齐
    void duiqi(char a[], char b[], int* flaga, int* flagb)
    {
        int lena_int = 0;   //a整数部分长度
        int lena_float = 0; //a小数部分长度
        int lenb_int = 0;   //b
        int lenb_float = 0;
        int i = 0;
        int t;
        int indexa, indexb;
        int lena, lenb;
    
        //正负数
        if (a[0] == '-')
        {
            *flaga = 1;
            a[0] = '0';
        }
        else
            *flaga = 0;
    
        if (b[0] == '-')
        {
            *flagb = 1;
            b[0] = '0';
        }
        else
            *flagb = 0;
    
    
    
        lena = strlen(a);
        lenb = strlen(b);
        //计算a的整数部分长度
        while (a[i] != '\0' && a[i] != '.')
        {
            lena_int++;
            i++;
        }
    
        //计算a的小数部分长度
        if (a[i] == '.')
        {
            i++;
            while (a[i] != '\0')
            {
                lena_float++;
                i++;
            }
        }
        //计算b的整数部分长度
        i = 0;
        while (b[i] != '\0' && b[i] != '.')
        {
            lenb_int++;
            i++;
        }
    
        //计算b的小数部分长度
        if (b[i] == '.')
        {
            i++;
            while (b[i] != '\0')
            {
                lenb_float++;
                i++;
            }
    
        }
    
        //对齐长度
        t = lena_float > lenb_float ? lena_float : lenb_float;
        t = t + (lena_int > lenb_int ? lena_int : lenb_int);
        t += 1; //加一个小数点,得到总长度
        a[t] = 0;
        b[t] = 0;
        if (lena_float > lenb_float) //a的小数部分比b长
        {
            //a整体右移
            indexa = t - 1;
            for (i = lena - 1; i >= 0; i--, indexa--)
                a[indexa] = a[i];
            //前面补0
            while (indexa >= 0)
            {
                a[indexa] = '0';
                indexa--;
            }
            //a的小数部分长,则b的小数部分补0,补0的个数为lena_float - lena_float
            indexb = t - 1;
            i = 0;
            while (i < lena_float - lenb_float)
            {
                b[indexb] = '0';
                indexb--;
                i++;
            }
            //b整体右移
            for (i = lenb - 1; i >= 0; i--, indexb--)
                b[indexb] = b[i];
            //b前面补0
            while (indexb >= 0)
            {
                b[indexb] = '0';
                indexb--;
            }
        }
        else //b的小数部分比a长
        {
            //b整体右移
            indexb = t - 1;
            for (i = lenb - 1; i >= 0; i--, indexb--)
                b[indexb] = b[i];
            //b前面补0
            while (indexb >= 0)
            {
                b[indexb] = '0';
                indexb--;
            }
            //a小数后面补0
            i = 0;
            indexa = t - 1;
            while (i < lenb_float - lena_float)
            {
                a[indexa] = '0';
                indexa--;
                i++;
            }
            //a整体右移
            for (i = lena - 1; i >= 0; i--, indexa--)
                a[indexa] = a[i];
            //a前面补0
            while (indexa >= 0)
            {
                a[indexa] = '0';
                indexa--;
            }
        }
        //输出对齐后的数
        /*printf("对齐后的数:\n");
        if (*flaga == 1)
            printf("-%s\n", a);
        else
            printf("+%s\n", a);
        if(*flagb == 1)
            printf("-%s\n", b);
        else
            printf("+%s\n", b);*/
    }
    
    //比较大小
    int isbig(char a[], char b[])
    {
        return strcmp(a, b);
    }
    
    
    //大数相加,在运算前,先将数字对齐
    void bigAdd(char a[], char b[], char c[])
    {
        int maxlen = strlen(a) + 1; //a和b等长度,结果的最大值是 strlen(a)+1
        int i, j, shift = 0, t = 0;
    
        for (i = 0; i < maxlen; i++)
            c[i] = '0'; //填充'0'
    
        c[maxlen] = 0;//结尾标记
        i = strlen(a) - 1;
        j = maxlen - 1;
    
        //计算小数部分
        while (a[i] != '.')
        {
            t = (a[i] - '0') + (b[i] - '0') + shift;
            if (t >= 10)
            {
                t -= 10;
                shift = 1;
                c[j] = '0' + t;
            }
            else
            {
                shift = 0;
                c[j] = '0' + t;
            }
            i--;
            j--;
        }
        c[j] = '.';
        i--;
        j--;
        while (i >= 0)
        {
            t = (a[i] - '0') + (b[i] - '0') + shift;
            if (t >= 10)
            {
                t -= 10;
                shift = 1;
                c[j] = '0' + t;
            }
            else
            {
                shift = 0;
                c[j] = '0' + t;
            }
            i--;
            j--;
        }
        if (shift)
            c[j] = '0' + shift;
        //删除前后的0
        deletePreZero(c);
        deleteBackZero(c);
    }
    
    //大数相减,在运算前,先将数字对齐,并用大数减去小数
    void bigSub(char a[], char b[], char c[])
    {
        int maxlen = strlen(a); //减法结果的长度不会超过元字符长度
        int i, j, t, shift = 0;
        for (i = 0; i < maxlen; i++)
            c[i] = '0'; //填充'0'
        c[maxlen] = 0; //结尾标记
    
        i = strlen(a) - 1;
        j = maxlen - 1;
        //计算小数部分
        while (a[i] != '.')
        {
            t = a[i] - b[i] - shift; //是否有借位
            if (t < 0)
            {
                t += 10;
                shift = 1;//有借位
                c[j] = '0' + t;
            }
            else
            {
                shift = 0;//无借位
                c[j] = '0' + t;
            }
            i--;
            j--;
        }
        c[j] = '.';
        i--;
        j--;
        //计算整数部分
        while (i >= 0)
        {
            t = a[i] - b[i] - shift; //是否有借位
            if (t < 0)
            {
                t += 10;
                shift = 1;//有借位
                c[j] = '0' + t;
            }
            else
            {
                shift = 0;//无借位
                c[j] = '0' + t;
            }
            i--;
            j--;
        }
        //删除前后的0
        deletePreZero(c);
        deleteBackZero(c);
    
    }
    //大数相乘
    void bigMul(char a[], char b[], char c[])
    {
        int lena = strlen(a);
        int lenb = strlen(b);
        int maxlen = lena + lenb + 1;
        int i, j, t, k, shift = 0;
        int indextmp;
        char tmp[MAXNUM * 2 + 1] = { 0 }; //存储临时结果
    
        //得到a和b的小数位数
        int lena_float = 0, lenb_float = 0;
        int ff = 0;
        i = 0;
        while (a[i] != '\0')
        {
            if (a[i] == '.')
                ff = 1;
            if (ff == 1 && a[i] >= '0' && a[i] <= '9')
                lena_float++;
            i++;
        }
        i = 0;
        ff = 0;
        while (b[i] != '\0')
        {
            if (b[i] == '.')
                ff = 1;
            if (ff == 1 && b[i] >= '0' && b[i] <= '9')
                lenb_float++;
            i++;
        }
    
    
    
        //初始化c
        for (i = 0; i < MAXNUM * 2; i++)
            c[i] = '0';
        c[MAXNUM * 2] = 0; //结尾
    
    
        for (i = lenb - 1, j = 0; i >= 0; i--)
        {
            if (b[i] == '.')
                continue;
            //重置tmp
            for (k = 0; k < MAXNUM * 2; k++)
                tmp[k] = '0';
            //tmp的偏移位
            indextmp = MAXNUM * 2 - j - 1;
            //用b的每一位去乘a,并存储到tmp中
    
            for (k = lena - 1; k >= 0; k--)
            {
                if (a[k] == '.')
                    continue;
                t = (b[i] - '0') * (a[k] - '0') + shift;
                if (t >= 10)
                {
                    shift = t / 10;
                    t = t % 10;
                }
                else
                {
                    shift = 0;
                }
                tmp[indextmp] = '0' + t;
                indextmp--;
            }
            if (shift)
            {
                tmp[indextmp] = '0' + shift;
                shift = 0;
            }
            //tmp与c相加
            //printf("tmp=%s\n", tmp);
            shift = 0;
            for (k = MAXNUM * 2 - 1; k >= 0; k--)
            {
                t = tmp[k] - '0' + c[k] - '0' + shift;
                if (t >= 10)
                {
                    t -= 10;
                    shift = 1;
                }
                else
                    shift = 0;
                c[k] = '0' + t;
            }
            j++;
        }
        //小数点的位数
        //printf("c=%s\n", c);
        for (i = 0; i < MAXNUM * 2 - (lena_float + lenb_float); i++)
            c[i] = c[i + 1];
        c[MAXNUM * 2 - lena_float - lenb_float - 1] = '.';
        //printf("c=%s\n", c);
    
        //删除前后的0
        deletePreZero(c);
    }
    
    int main()
    {
        char a[MAXNUM + 1], b[MAXNUM + 1], c[MAXNUM * 2 + 1];
        int flaga, flagb;
        int ret;
        //strcpy(a, "54375594968196412353419.7136567768967814548988");
        //strcpy(b, "73287424855639561252347.4564956732129084076487");
        scanf("%s", a);
        scanf("%s", b);
        duiqi(a, b, &flaga, &flagb); //对齐处理后,消除了a和b的符号位,a和b中只保留数字部分,flaga和flagb记录a和b的正负性
    
        if (flaga == 0 && flagb == 0) //都是正数
        {
            bigAdd(a, b, c); //加法
            printf("%s\n", c);
            //减法,用大数减去小数,并根据符号决定是否取反
            ret = isbig(a, b);
            if (ret == 1)
            {
                bigSub(a, b, c);
                printf("%s\n", c);
            }
            else if (ret == 0)
                printf("0\n");
            else
            {
                bigSub(b, a, c);
                printf("-%s\n", c);
            }
            //乘法
            deleteBackZero(a);
            deletePreZero(a);
            deleteBackZero(b);
            deleteBackZero(b);
            bigMul(a, b, c);
            printf("%s\n", c);
        }
        else if (flaga == 0 && flagb == 1) //a是正数,b是负数
        {
            //加法,因有负数,实际调用减法求加法的结果
            ret = isbig(a, b);
            if (ret == 1)
            {
                bigSub(a, b, c);
                printf("%s\n", c);
            }
            else if (ret == 0)
                printf("0\n");
            else
            {
                bigSub(b, a, c);
                printf("-%s\n", c);
            }
            //减法,实际是加法
            bigAdd(a, b, c);
            printf("%s\n", c);
            //乘法
            deleteBackZero(a);
            deletePreZero(a);
            deleteBackZero(b);
            deleteBackZero(b);
            bigMul(a, b, c);
            printf("-%s\n", c);
    
        }
        else if (flaga == 1 && flagb == 0) //a是负数,b是正数
        {
            //加法,实际是减法
            ret = isbig(b, a);
            if (ret == 1)
            {
                bigSub(b, a, c);
                printf("%s\n", c);
            }
            else if (ret == 0)
                printf("0\n");
            else
            {
                bigSub(a, b, c);
                printf("-%s\n", c);
            }
            //减法,实际是加法,结果取反
            bigAdd(a, b, c);
            printf("-%s\n", c);
            //乘法
            deleteBackZero(a);
            deletePreZero(a);
            deleteBackZero(b);
            deleteBackZero(b);
            bigMul(a, b, c);
            printf("-%s\n", c);
        }
        else //都是负数
        {
            //加法,结果取反
            bigAdd(a, b, c);
            printf("-%s\n", c);
            //减法,实际是b-a
            ret = isbig(b, a);
            if (ret == 1)
            {
                bigSub(b, a, c);
                printf("%s\n", c);
            }
            else if (ret == 0)
                printf("0\n");
            else
            {
                bigSub(a, b, c);
                printf("-%s\n", c);
            }
            //乘法
            deleteBackZero(a);
            deletePreZero(a);
            deleteBackZero(b);
            deleteBackZero(b);
            bigMul(a, b, c);
            printf("%s\n", c);
        }
    
    
        return 0;
    }
    
    
    
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 6月14日
  • 已采纳回答 6月6日
  • 创建了问题 6月6日

悬赏问题

  • ¥15 模电中二极管,三极管和电容的应用
  • ¥15 关于模型导入UNITY的.FBX: Check external application preferences.警告。
  • ¥15 气象网格数据与卫星轨道数据如何匹配
  • ¥100 java ee ssm项目 悬赏,感兴趣直接联系我
  • ¥15 微软账户问题不小心注销了好像
  • ¥15 x264库中预测模式字IPM、运动向量差MVD、量化后的DCT系数的位置
  • ¥15 curl 命令调用正常,程序调用报 java.net.ConnectException: connection refused
  • ¥20 关于web前端如何播放二次加密m3u8视频的问题
  • ¥15 使用百度地图api 位置函数报错?
  • ¥15 metamask如何添加TRON自定义网络