今天这道题目呢,与前天讲的“龟兔赛跑”都是从PAT的基础编程题目中节选过来的。
难度不是很大,但是特别基础,复习到了基础知识,也就是二进制、十进制两者之间的相互转换。
我们先来看看这道题目的要求:
BCD数是用一个字节来表达两位十进制的数,每四个比特表示一位。
所以,如果一个BCD数的十六进制为0x12,那么它的十进制也是12。
此时有一位小伙伴并不知道BCD数的运算规则,直接把0x12当作二进制来转换成十进制,那就会得到18。
现在呢,我们就期望能把这个错误得到的十进制,转换成我们期望得到的十进制数值。
给定的这个错误十进制范围为[0,153]。
题目要求呢我们都清楚了,接下来就是如何解决这个问题。
这里呢,主要涉及到的是十六进制和十进制之间以及二进制和十进制之间的转换。
但我呢,好像把这道题目给想复杂了emm,结果导致简单问题复杂化,实在是不应该啊。
理清逻辑,画出流程图,这是十进制转换为二进制再进行BCD解密
程序要写正确的话,流程图用来帮助理清逻辑非常好用,这张流程图画的有些小,真的有些不好意思。
可以从这张流程图中看出来,我的逻辑就是:
把该同学输入的整数先转换为二进制数,比方说给定的十进制数为18。
那么转换成的二进制数则为00010010。
之后再把二进制数转换为十六进制的形式则为0001和0010。
之后分别转换为十进制得到1和2。
然后求和1*10+2*1=12,最终得到结果。
我的代码部分:
注意,这里我用到了一个pow函数,这是一个求幂次方的函数,在用这个函数的时候,需要调用库#include<math.h>。
#include<stdio.h>
#include<math.h>
int main(){
int number = 0;//初始化定义需要输入的十进制数
int store[8] = {0};
int mod = 0;
int mild1 = 0;//求和
int mild2 = 0;//求和
scanf("%d", &number);
for(int i = 0; i < 8; i++){
mod = number%2;
number = number/2;
store[i] = mod;
}
for(int i = 7; i >= 4; i--){
if(store[i]==1){
mild1 = mild1+pow(2,i-4);
}
}
for(int i = 3; i >= 0; i--){
if(store[i]==1){
mild2 = mild2+pow(2,i);
}
}
printf("%d", mild1*10+mild2);
printf("n");
}
测试结果:
提交PAT测试结果:
但是呢,我在思考,这道题目有没有更快的方法了。
毕竟这样从二进制开始写,十进制转化为二进制,然后再转化为十六进制,然后分开二进制转化为十进制的确麻烦了些。
于是,我再来认真地读了一遍这道题。
读来读去,只发现这道题是只需要我们直接把十进制转化为十六进制即可!然后再直接计算不就行了么。
BCD太迷惑人了!
十进制转化为十六进制的流程:
给定一个数18,18除以16等于1取余数得到2,再把1除以16等于0取余数得到1。
1和2组合起来,不也能得到最终结果吗?
流程图,这是十进制转换为十六进制再进行BCD解密
我的代码部分
#include<stdio.h>
int main(){
int number = 0;//初始化定义需要输入的十进制数
int store[8];
int mod = 0;
scanf("%d", &number);
for(int i = 0; i < 8; i++){
mod = number%16;
number = number/16;
store[i] = mod;
}
printf("%d",store[1]*10+store[0]);
}
测试结果
提交PAT测试结果
总结
在做这道题目的时候,我遇到了很多很多问题。
比方说逆序输出的时候,我直接把1和2按照顺序打出,但这样的话就会产生问题,最小值该如何判断。
还有要用到pow函数,这个可不能忘了。
总的来说,这道题呢,关键还是考我们对十进制、二进制和十六进制之间的转换是否熟悉。
如果很熟悉的话,这道题目直接十进制与十六进制转换一下就做出来了。
没必要像我最开始写的那样兜一个大圈子。