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

(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;
}




您好,我是有问必答小助手,您的问题已经有小伙伴帮您解答,感谢您对有问必答的支持与关注!
PS:问答VIP年卡 【限时加赠:IT技术图书免费领】,了解详情>>> https://vip.csdn.net/askvip?utm_source=1146287632