这道题其实我们都走错方向了?
/*C2-2 进制转换 (100 满分)
题目描述
已知一个只包含 0 和 1 的二进制数,长度不大于 10 ,将其转换为十进制并输出。
输入描述
输入一个二进制整数n,其长度大于0且不大于10
输出描述
输出转换后的十进制数, 占一行
样例输入
110
样例输出
6*/
包括本人在内,在思考此题时都走错了方向,卡在了计算二进制整数长度上。有人说,用字符一个个接收字符类型的整数再一个个转换为整数,顺便计数,还有人说利用异或等原理用循环将数的二进制反复向右移动,还有人说,用c++自带的库函数直接实现转换,还有人说......等等等等,直到本人在csdn上看到了一个算法,才恍然大悟,之前你们都走错方向了!其实这道题不就是将整数倒着输出的变式么?只不过多了模数2,还记得将整数倒着输出的算法吗?
#include<iostream>
using namespace std;
int main()
{/*Reverse digit */
int m,n;
cout<<"Please input:"<<endl;
cin>>m;
do{
n=m%10;
cout<<n;
m/=10;
}while(m);
cout<<endl;
}
比如输入123,怎么办,是不是先对123模10取余?,取出来的是什么?当前n的末位3,3取出来了,输出,再想输出2,怎么办?用除操作将123“砍掉”1个3,现在m=12,n=3,下一循环,12去模10取余取到2,n=2输出,再通过除操作“砍掉”末位2,重复上述过程,直到m=0,上述过程反复进行的就是模10取余取到最低位拿来用,取好了用除操作“砍掉”最低位继续。有人可能会说“我还是不明白这和二进制转十进制有什么关系”。别急,我们先来看看二进制是怎么转为十进制的吧!
假如给出整数0111,你是怎么转换的?是不是0x2的3次+1x2的2次+1x2的1次+1x2的0次?那么不是就可以依次从最低位取到最高位,每取1位进行操作了吗?不过在此之前要注意下0111在计算机中就是111,前面的0忽略的。好了,我们来分析下具体过程。
首先将0111模10取最低位1,进行模数为2的操作,也就是用1去乘2的0次,再用除操作“砍掉”当前最低位的1,再模10取最低位,进行模数为2的操作,也就是用1去乘2的1次,再用除操作“砍掉”当前最低位1,如此循环,直到0111为0!
模数为2的操作可以调用数学函数库,也可以用*=操作,都可以。下面是具体代码:
#include<iostream>
using namespace std;
int main()
{
int n,r,m=1,sum=0;
cin>>n;
do{
r=n%10;//取余
sum+=r*m;//累加余数乘以模数m
m*=2;//模数乘以2
n/=10;//n除以10
}while(n);
cout<<sum;//输出累加和
return 0;
}
第一次看到这些代码的时候,真是感叹之前的我太愚蠢了,绕了一大圈,结果还是将整数倒着输出那道简单题目的变式!!不过这代码确实相比精简多了,又易懂,你看核心算法才4行,多么漂亮!
这件事告诉我们,题目往往没我们想得那么复杂,要不断注意知识迁移,才能锻炼发散思维,提高分析能力,最终达到万变不离其宗!
上一篇: 算法-栈-十进制转二进制
下一篇: C语言 十进制转换成二进制
推荐阅读