首页 > 试题广场 >

浮点数加法

[编程题]浮点数加法
  • 热度指数:22723 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
求2个浮点数相加的和 题目中输入输出中出现浮点数都有如下的形式: P1P2...Pi.Q1Q2...Qj 对于整数部分,P1P2...Pi是一个非负整数 对于小数部分,Qj不等于0

输入描述:
对于每组案例,每组测试数据占2行,分别是两个加数。


输出描述:
每组案例是n行,每组测试数据有一行输出是相应的和。
输出保证一定是一个小数部分不为0的浮点数
示例1

输入

0.111111111111111111111111111111
0.111111111111111111111111111111

输出

0.222222222222222222222222222222
主要还是权值对齐,处理好进位

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

// 反转字符串函数
// 功能:将输入的字符串进行反转,方便后续的加法运算从低位开始处理
// 参数:str 为待反转的字符串
void reverse(char *str) {
    // 获取字符串的长度
    int len = strlen(str);
    // 遍历字符串的前半部分
    for (int i = 0; i < len/2; i++) {
        // 交换当前字符和对称位置的字符
        char temp = str[i];
        str[i] = str[len-i-1];
        str[len-i-1] = temp;
    }
}

// 小数相加(返回进位)
// 功能:将两个以字符串形式表示的小数部分相加,并返回相加后产生的进位
// 参数:dec1 为第一个小数部分的字符串,dec2 为第二个小数部分的字符串,result 用于存储相加结果
int add_decimal(char *dec1, char *dec2, char *result) {
    // 获取 dec1 的长度
    int len1 = strlen(dec1);
    // 获取 dec2 的长度
    int len2 = strlen(dec2);
    // 找出两个小数部分长度的最大值
    int max_len = len1 > len2 ? len1 : len2;

    // 补零对齐
    // 动态分配内存,用于存储补零后的 dec1,长度为 max_len + 1(包含字符串结束符)
    char *temp1 = calloc(max_len+1, sizeof(char));
    // 动态分配内存,用于存储补零后的 dec2,长度为 max_len + 1(包含字符串结束符)
    char *temp2 = calloc(max_len+1, sizeof(char));
    // 将 dec1 复制到 temp1 中
    strcpy(temp1, dec1);
    // 将 dec2 复制到 temp2 中
    strcpy(temp2, dec2);
    // 若 dec1 的长度小于 max_len,在 temp1 后面补零
    for (int i = len1; i < max_len; i++) temp1[i] = '0';
    // 若 dec2 的长度小于 max_len,在 temp2 后面补零
    for (int i = len2; i < max_len; i++) temp2[i] = '0';

    // 从右往左相加
    // 初始化进位为 0
    int carry = 0;
    // 用于记录结果字符串的索引
    int k = 0;
    // 从右往左逐位相加
    for (int i = max_len-1; i >= 0; i--) {
        // 计算当前位的和,包括进位
        int sum = (temp1[i]-'0') + (temp2[i]-'0') + carry;
        // 将当前位的和对 10 取模,得到当前位的结果,并转换为字符存储到 result 中
        result[k++] = sum % 10 + '0';
        // 计算新的进位
        carry = sum / 10;
    }
    // 在结果字符串末尾添加字符串结束符
    result[k] = '\0';
    // 反转结果字符串,因为之前是从低位到高位存储的
    reverse(result);

    // 去除末尾多余的零
    // 当结果字符串末尾有零且长度大于 0 时,将零去除
    while (k > 0 && result[k-1] == '0') result[--k] = '\0';
    
    // 释放动态分配的内存
    free(temp1);
    free(temp2);
    // 返回小数相加后产生的进位
    return carry;
}

// 整数相加(修复补零方式)
// 功能:将两个以字符串形式表示的整数部分相加,并将结果存储在 result 中
// 参数:int1 为第一个整数部分的字符串,int2 为第二个整数部分的字符串,result 用于存储相加结果
void add_integer(char *int1, char *int2, char *result) {
    // 获取 int1 的长度
    int len1 = strlen(int1);
    // 获取 int2 的长度
    int len2 = strlen(int2);
    // 找出两个整数部分长度的最大值
    int max_len = len1 > len2 ? len1 : len2;

    // 补前导零对齐
    // 动态分配内存,用于存储补零后的 int1,长度为 max_len + 1(包含字符串结束符)
    char *temp1 = calloc(max_len+1, sizeof(char));
    // 动态分配内存,用于存储补零后的 int2,长度为 max_len + 1(包含字符串结束符)
    char *temp2 = calloc(max_len+1, sizeof(char));
    // 将 temp1 初始化为全零
    memset(temp1, '0', max_len);
    // 将 temp2 初始化为全零
    memset(temp2, '0', max_len);
    // 将 int1 复制到 temp1 的合适位置,前面补零
    strcpy(temp1 + (max_len - len1), int1);
    // 将 int2 复制到 temp2 的合适位置,前面补零
    strcpy(temp2 + (max_len - len2), int2);

    // 从右往左相加
    // 初始化进位为 0
    int carry = 0;
    // 用于记录结果字符串的索引
    int k = 0;
    // 从右往左逐位相加
    for (int i = max_len-1; i >= 0; i--) {
        // 计算当前位的和,包括进位
        int sum = (temp1[i]-'0') + (temp2[i]-'0') + carry;
        // 将当前位的和对 10 取模,得到当前位的结果,并转换为字符存储到 result 中
        result[k++] = sum % 10 + '0';
        // 计算新的进位
        carry = sum / 10;
    }
    // 如果最后还有进位,将进位添加到结果字符串中
    if (carry) result[k++] = '1';
    // 在结果字符串末尾添加字符串结束符
    result[k] = '\0';
    // 反转结果字符串,因为之前是从低位到高位存储的
    reverse(result);

    // 去除前导零
    // 找到第一个非零字符的位置
    int start = 0;
    // 当结果字符串有前导零且不是最后一个字符时,继续查找
    while (result[start] == '0' && start < k-1) start++;
    // 将从第一个非零字符开始的子字符串移动到结果字符串的开头
    memmove(result, result + start, k - start + 1);

    // 释放动态分配的内存
    free(temp1);
    free(temp2);
}

int main() {
    // 定义两个字符数组,用于存储输入的两个浮点数
    char num1[1000], num2[1000];
    // 循环读取多组输入,直到文件结束
    while (scanf("%s %s", num1, num2) != EOF) {
        // 定义四个字符数组,分别用于存储两个浮点数的整数部分和小数部分
        char int1[1000], int2[1000], dec1[1000], dec2[1000];
        // 定义两个字符数组,分别用于存储整数部分和小数部分相加的结果,并初始化为全零
        char result_int[1000] = {0}, result_dec[1000] = {0};

        // 提取整数和小数部分
        // 在 num1 中查找小数点的位置
        char *dot = strchr(num1, '.');
        if (dot) {
            // 复制 num1 的整数部分到 int1 中
            strncpy(int1, num1, dot - num1);
            // 在 int1 末尾添加字符串结束符
            int1[dot - num1] = '\0';
            // 复制 num1 的小数部分到 dec1 中
            strcpy(dec1, dot + 1);
        } else {
            // 如果 num1 中没有小数点,整个字符串就是整数部分
            strcpy(int1, num1);
            // 小数部分为空
            dec1[0] = '\0';
        }

        // 在 num2 中查找小数点的位置
        dot = strchr(num2, '.');
        if (dot) {
            // 复制 num2 的整数部分到 int2 中
            strncpy(int2, num2, dot - num2);
            // 在 int2 末尾添加字符串结束符
            int2[dot - num2] = '\0';
            // 复制 num2 的小数部分到 dec2 中
            strcpy(dec2, dot + 1);
        } else {
            // 如果 num2 中没有小数点,整个字符串就是整数部分
            strcpy(int2, num2);
            // 小数部分为空
            dec2[0] = '\0';
        }

        // 处理小数部分
        // 调用 add_decimal 函数计算小数部分相加的结果,并获取进位
        int carry_dec = add_decimal(dec1, dec2, result_dec);
        
        // 处理整数部分(包含小数进位)
        if (carry_dec) {
            // 定义一个字符串表示进位 1
            char carry_str[] = "1";
            // 先将进位加到 int1 上
            add_integer(int1, carry_str, int1); 
        }
        // 再加两个整数部分
        add_integer(int1, int2, result_int); 

        // 输出最终结果
        // 如果小数部分不为空,输出整数部分、小数点和小数部分;否则只输出整数部分
        printf("%s%s%s\n", 
            result_int, 
            strlen(result_dec) ? "." : "", 
            strlen(result_dec) ? result_dec : "");
    }
    return 0;
}

发表于 2025-03-10 20:04:05 回复(0)
#include<stdio.h>
#include<string.h>
int main(void){
    char a[100],b[100];
    scanf("%s %s",a,b);
    int len1,len2;
    len1=strlen(a);
    len2=strlen(b);
    int jinwei=0;
    int ap,bp;
    //找小数点的位置
    for(int i=0;i<len1;i++){
        if(a[i]=='.'){
            ap=i;
        }
    }
    for(int i=0;i<len2;i++){
        if(b[i]=='.'){
            bp=i;
        }
    }
    //先计算小数部分
    //对长度较短的那个数进行扩充
    int _len1=len1-ap-1;
    int _len2=len2-bp-1;
    int cha;
    int z_len;
    if(_len1>_len2){
        cha=_len1-_len2;
        for(int i=len2;i<len2+cha;i++){
            b[i]='0';
        }
        z_len=_len1;
    }else{
        cha=_len2-_len1;
        for(int i=len1;i<len1+cha;i++){
            a[i]='0';
       }
        z_len=_len2;
    }

    int sum[z_len];
    int temp=0;
    int xs_jw;
    for(int i=z_len-1;i>-1;i--){
        sum[i]=(a[ap+i+1]-48+b[bp+i+1]-48+temp)%10;
        temp=(a[ap+i+1]-48+b[bp+i+1]-48+temp)/10;
    }
    
    xs_jw=temp;
//     printf("小数部分相加结果:\n");
//     for(int i=0;i<z_len;i++){
//         printf("%d ",sum[i]);
//     }
//     printf("\n");
//     printf("小数部分相加进位:\n");
//     printf("%d",xs_jw);
//     printf("\n");
    
    
    //再计算整数部分
    //在短的前面补零
    int zz_len;
    if(ap>bp){ //b较短
        zz_len=ap;
        cha=ap-bp;
        for(int i=bp-1;i>-1;i--){
            b[i+cha]=b[i];
        }
        //补充前面的0
        for(int i=0;i<cha;i++){
            b[i]='0';
        }
        
    }else{
        zz_len=bp;
        cha=bp-ap;
        for(int i=ap-1;i>-1;i--){
            a[i+cha]=a[i];
        }
        //补充前面的0
        for(int i=0;i<cha;i++){
            a[i]='0';
        }
    }
    
    
    
    
    
    int sum2[zz_len];
    int temp2=xs_jw;
    int zs_jw;
    for(int i=zz_len-1;i>-1;i--){
        sum2[i]=(a[i]-48+b[i]-48+temp2)%10;
//         printf("%d  ",sum2[i]);
        temp2=(a[i]-48+b[i]-48+temp2)/10;
//         printf("%d  ",temp2);
//         printf("\n");
    }
    
    zs_jw=temp2;
//     printf("整数部分相加结果:\n");
//     for(int i=0;i<zz_len;i++){
//         printf("%d ",sum2[i]);
//     }
//     printf("\n");
//     printf("整数部分相加进位:\n");
//     printf("%d",zs_jw);
//     printf("\n");
    
    
//     printf("最后的结果:");
    if(zs_jw!=0){
       printf("%d",zs_jw);
        }
     for(int i=0;i<zz_len;i++){
            printf("%d",sum2[i]);
    }
    printf(".");
    for(int i=0;i<z_len;i++){
            printf("%d",sum[i]);
    }
    
    return 0;
}

发表于 2022-03-19 16:39:07 回复(0)

问题信息

难度:
3条回答 10764浏览

热门推荐

通过挑战的用户

查看代码
浮点数加法