「PAT乙级真题解析」Basic Level 1074 宇宙无敌加法器 (问题分析+完整步骤+伪代码描述+提交通过代码)

题设给定三个字符串, 第一个字符串代表各个数位的进制数, 第二个和第三个字符串代表十进制数值(题目说是PAT数, 但是当成十进制数处理就可以)。 要求将两个数值相加之后按照给定的各个数位进制进位之后, 输出相加结果。 由于给定的两个数位数不一定相同, 所以我们需要高位补零让两个数值位数相同, 然后从末尾开始往最高位, 按位相加然后进位计算两数之和。

#算法#数据结构#pat考试#c语言#需求分析

Table of Contents

乙级的题目训练主要用来熟悉编程语言的语法和形成良好的编码习惯和编码规范。从小白开始逐步掌握用编程解决问题。

PAT (Basic Level) Practice 1074 宇宙无敌加法器

问题分析

  • 题设给定三个字符串, 第一个字符串代表各个数位的进制数, 第二个和第三个字符串代表十进制数值(题目说是PAT数, 但是当成十进制数处理就可以)。
  • 要求将两个数值相加之后按照给定的各个数位进制进位之后, 输出相加结果。
  • 由于给定的两个数位数不一定相同, 所以我们需要高位补零让两个数值位数相同,
  • 然后从末尾开始往最高位, 按位相加然后进位计算两数之和。

样例

输入:
30527
06203
415
计算过程:
进制: 3 0 5 2 7
数一: 0 6 2 0 3
数二: 0 0 4 1 5
     | | | | ↓
     | | | | 3+5 % 7 = 1 进位: 1
     | | | ↓
     | | | 0+1+1 % 2 = 0 进位: 1
     | | ↓
     | | 2+4+1 % 5 = 2 进位: 1
     | ↓
     | 6+0+1 % 10 = 7 进位: 0
     ↓
     0+0+0 % 3 = 0 进位: 0

结果: 0 0 7 2 0 1
(最高位进位) + (各个数位余数)
输出: 7201

完整描述步骤

  1. 获取输入: 各个数位的进制, 数值字符串一, 数值字符串二
  2. 补齐两个数值的长度:
    • 计算两个进制表的长度
    • 如果数值字符串一长度小于进制表长度, 则高位补0
    • 如果数值字符串二长度小于进制表长度, 则高位补0
  3. 初始化记录器:
    • 当前进位值 = 0
  4. 从数值字符串末尾开始:
    • 计算两个数值字符串当前数位的数字和
    • 计算余数: 将数字和对进制表的进制取余
    • 计算当前进位值 = 数字和 / 当前进制
  5. 如果 当前进位值 == 1:
    • 先输出一个"1"
    • 直接输出数值和计算结果
    • 结束程序
  6. 找到第一个非零的字符, 然后输出从非零字符开始到结尾的字符串
  7. 如果字符串全由0组成, 输出"0"

伪代码描述

  1. get input: radixes, number_1, number_2
  2. fill zero at the front of the numbers:
    • if length(number_1) < length(radixes):
      • number_1 = "0" * (length(radixes) - length(number_1)) + number_1;
    • if length(number_2) < length(radixes):
      • number_2 = "0" * (length(radixes) - length(number_2)) + number_2;
  3. init recorder:
    • carry = 0;
    • numbers_sum;
  4. for idx in range(length(radixes), -1, -1):
    • numbers_sum[idx] = number_1[idx] + number_2[idx];
    • carry = numbers_sum[idx] / radixes[idx]
    • numbers_sum[idx] = numbers_sum[idx] % radixes[idx]
  5. if carry == 1:
    • print("1{numbers_sum}");
    • end procedure;
  6. for idx in range(0, length(radixes)):
    • if numbers_sum[idx] != '0':
      • print(numbers_sum[idx:])
      • end procedure
  7. print("0");

注意事项

  1. 测试点3、测试点4: 最高位是否需要进位, 比如"30527\n30527\n0"应该输出"101110"
  2. 测试点5: 相加结果为0, 需要输出"0", 不能不输出任何字符.

完整提交代码

/*
# 问题分析
题设给定三个字符串, 第一个字符串代表各个数位的进制数, 第二个和第三个字符串代表十进制数值(题目说是PAT数, 但是当成十进制数处理就可以)。
要求将两个数值相加之后按照给定的各个数位进制进位之后, 输出相加结果。
由于给定的两个数位数不一定相同, 所以我们需要高位补零让两个数值位数相同,
然后从末尾开始往最高位, 按位相加然后进位计算两数之和。
 
## 样例
输入:
30527
06203
415
计算过程:
进制: 3 0 5 2 7
数一: 0 6 2 0 3
数二: 0 0 4 1 5
     | | | | ↓
     | | | | 3+5 % 7 = 1 进位: 1
     | | | ↓
     | | | 0+1+1 % 2 = 0 进位: 1
     | | ↓
     | | 2+4+1 % 5 = 2 进位: 1
     | ↓
     | 6+0+1 % 10 = 7 进位: 0

     0+0+0 % 3 = 0 进位: 0
 
结果: 0 0 7 2 0 1
(最高位进位) + (各个数位余数)
输出: 7201
 
# 完整描述步骤
1. 获取输入: 各个数位的进制, 数值字符串一, 数值字符串二
2. 补齐两个数值的长度:
    - 计算两个进制表的长度
    - 如果数值字符串一长度小于进制表长度, 则高位补0
    - 如果数值字符串二长度小于进制表长度, 则高位补0
3. 初始化记录器:
    - 当前进位值 = 0
4. 从数值字符串末尾开始:
    - 计算两个数值字符串当前数位的数字和
    - 计算余数: 将数字和对进制表的进制取余
    - 计算当前进位值 = 数字和 / 当前进制
5. 如果 当前进位值 == 1:
    - 先输出一个"1"
    - 直接输出数值和计算结果
    - 结束程序
6. 找到第一个非零的字符, 然后输出从非零字符开始到结尾的字符串
7. 如果字符串全由0组成, 输出"0"
 
# 伪代码描述
1. get input: radixes, number_1, number_2
2. fill zero at the front of the numbers:
    - if length(number_1) < length(radixes):
        - number_1 = "0" * (length(radixes) - length(number_1)) + number_1;
    - if length(number_2) < length(radixes):
        - number_2 = "0" * (length(radixes) - length(number_2)) + number_2;
3. init recorder:
    - carry = 0;
    - numbers_sum;
4. for idx in range(length(radixes), -1, -1):
    - numbers_sum[idx] = number_1[idx] + number_2[idx];
    - carry = numbers_sum[idx] / radixes[idx]
    - numbers_sum[idx] = numbers_sum[idx] % radixes[idx]
5. if carry == 1:
    - print("1{numbers_sum}");
    - end procedure;
6. for idx in range(0, length(radixes)):
    - if numbers_sum[idx] != '0':
        - print(numbers_sum[idx:])
        - end procedure
7. print("0");
 
# 注意事项
1. 测试点3、测试点4: 最高位是否需要进位, 比如"30527\n30527\n0"应该输出"101110"
2. 测试点5: 相加结果为0, 需要输出"0", 不能不输出任何字符.
 
*/
 
# include<stdio.h>
# include<string.h>
# define MAX_LENGTH 30
 
void zero_fill_at_the_front(int size, char* number, int target_size){
    number[target_size] = 0;
    for (int i = 0; i < size; i++){
        number[target_size - 1 - i] = number[size - 1 - i];
    }
    for (int i = 0; i < target_size - size; i++){
        number[i] = '0';
    }
}
 
int main(){
    char radixes[MAX_LENGTH];
    char number_1[MAX_LENGTH];
    char number_2[MAX_LENGTH];
 
    scanf("%s\n%s\n%s", radixes, number_1, number_2);
 
    int digit_amount = strlen(radixes);
    int size_1 = strlen(number_1);
    int size_2 = strlen(number_2);
 
    if (size_1 < digit_amount){
        zero_fill_at_the_front(size_1, number_1, digit_amount);
    }
    if (size_2 < digit_amount){
        zero_fill_at_the_front(size_2, number_2, digit_amount);
    }
    
    
    char result[MAX_LENGTH];
    memset(result, 0, MAX_LENGTH);
    int carry = 0;
    for ( int i = digit_amount - 1; i >= 0; i--){
        int radix = radixes[i] - '0';
        if (radix == 0){
            radix = 10;
        }
        
        int digit_1 = number_1[i] - '0';
        int digit_2 = number_2[i] - '0';
        int digit_result = (digit_1 + digit_2 + carry) % radix;
        result[i] = '0' + digit_result;
        carry = (digit_1 + digit_2 + carry) / radix;
    }
    
    if (carry == 1){
        printf("1%s", result);
        return 0;
    }
 
    for ( int i = 0; i < digit_amount; i++){
        if (result[i] != '0'){
            printf("%s", result + i);
            return 0;
        }
    }
    
    printf("0");
    return 0;
}
「PAT乙级真题解析」Basic Level 1074 宇宙无敌加法器 (问题分析+完整步骤+伪代码描述+提交通过代码) | 生活糖果