基数为正数的进制转换
“数制”只是一套符号系统来表示指称“量”的多少。我们用“1”这个符号来表示一个这一“量”的概念。自然界的“量”是无穷的,我们不可能为每一个“量”都造一个符号,这样的系统没人记得住。所以必须用有限的符号按一定的规律进行排列组合来表示这无限的“量”。符号是有限的,这些符号按照某种规则进行排列组合的个数是无限的。十进制是10个符号的排列组合,二进制是2个符号的排列组合。其他可以同理推出。
在进行进制转换时有一基本原则:转换后表达的“量”的多少不能发生改变。二进制中的111个苹果和十进制中的7个苹果是一样多的。
我们可以用短除法来进行进制转换。
为什么短除法可以实现进制的转换呢?为什么每次要除以进制呢?为什么要把余数倒着排列呢?
想要知道其中的道理的话,请仔细品味以下的递归原理(不知道递归没关系):
(1)一个十进制数321的末尾是1,意味着一定是……+1,省略号部分一定是10的倍数,所以一个十进制数末尾是1意味着十进制数除以进制10一定余1。所以第一次除以10之后的余数,应该放在十进制的最后一个数位“个位”,也就是说个位上的符号是1。
类比,一个二进制数111(注意,数值不等于上面十进制的111)末尾是1,意味着一定是……+1,前面的省略号部分都是2的倍数。所以一个二进制数末尾是1,意味着它对应的十进制数除以进制2一定余1。所以第一次除以2之后的余数,应该放在二进制的最后一个数位“一位”,也就是说一位上的符号是1。
(2)如果一个十进制数321“十位”是2,我们希望把它转换为(1)的情况。那么我们把这个十进制数的末尾抹掉,也就是减去“个位”上的1,再除以进制10,得到32。这样原来“十位”上的“2”就掉到了“个位”上。再把32做(1)的处理。
类比,如果一个二进制数111“二位”是1,我们希望把它转换为(1)的情况,那么我们把这个二进制数的末尾抹掉,也就是减去“一位”上的1,再除以进制2,得到11。这样原来“二位”上的“1”就掉到了“一位”上。再把11做(1)的处理。
总结:其实这个过程就是把各个数位上的符号求出来的过程。
现在应该明白了进制转化了吧!
那就.......看看代码?
输入一个十进制整数n,转为基数为r的数字。(2<=r)
#include<iostream>
#include<stack>
using namespace std;
char js[]="0123456789ABCDEFGH";
int main()
{
int n,r;
stack a;
cin>>n>>r;
while(n)
{
int mod=n%r;//余数
a.push(mod);
n/=r;
}
while(!a.empty())
{
cout<<js[a.top()];
a.pop();
}
}
你可能会问,为什么用stack来倒序输出,在代码中,我们先让入栈的数是低位,这下理解了吧!
基数为负数的进制转换
基数为负数与基数为正数相同,只不过需要注意余数为负数的情况。
当余数为负数时,我们就需要将其调整为正数。
调整方法:余数+=进制基数,商++
#include <bits/stdc++.h>
using namespace std;
int main()
{
char js[]="0123456789ABCDEFG";/
int n,r;
scanf("%d%d",&n,&r);
printf("%d=",n);//提前输出n,因为后面n变化了,如果想在后面输出,就要多加一个变量保存n
stack<int>s;//用栈来保存倒序的结果,便于输出
while(n){
int a=n%r;
n/=r;
if(a<0) {a-=r;n++;}//如果余数为负数,余数减去进制数,商加1
s.push(a);//结果进栈
}
while(!s.empty()){//输出结果
printf("%c",js[s.top()]);
s.pop();
}
printf("(base%d)\n",r);
return 0;
}