题目:进制转换
题目来源:洛谷P1017
题目描述
将正整数N转换成进制R的数。其中比较棘手的情况是基数R是负数的情况,因为这时用一般的取模运算,得到的的数码范围是[(R+1),0]。但规定此时的数码依然是非负数。
例如:-16的-2进制表示可以作以下运算:
−
16
=
1
∗
(
−
2
)
5
+
1
∗
(
−
2
)
4
-16=1*(-2)^5+1*(-2)^4
−16=1∗(−2)5+1∗(−2)4
即-16的-2进制表示为:11 0000
输入:输入的每行有两个输入数据。
第一个是十进制数 n。 第二个是负进制数的基数 -R。
输出:输出此负进制数及其基数,若此基数超过 10,则参照 16 进制的方式处理。
输入输出实例:输入 30000 -2 输出 30000=11011010101110000(base-2)
题目分析
首先要了解到C++里的 % 运算符的计算方法:r=m%n 是用
r
=
m
−
(
m
/
n
)
∗
n
[
1
]
r= m- (m/n)*n [1]
r=m−(m/n)∗n[1]
得到的,注意m/n为整除法。
可以看出:* 如果m是负数,那么r也一定是负数 *
还是用上面的-16作为例子,如果-16的-2进制按上面的[1]式计算,最后得到的结果是:(-1)0000,这时候的数码显然是不符合要求的。
分析运算过程,如果第i位的数码ri为负,(i从0开始算,是基数的次数)此时i一定为偶数。要得到非负数的数码,需要 1*Ri+1去加上 |ri|*Ri,因为i是偶数,Ri+1是负的,运算得到的结果是一样的。
总结:设m/n=q(整除), r=m%n
有(q+1)*n+(r-n)=q*n+n+r-n=q*n+r=m
这个时候的r一定是正的。
代码
#include<iostream>
using namespace std;
void convert(int n, int r);
char charac[20]={0}; //用于大于10进制的输出,由于最大是20进制,所以就开到20个
int main()
{
int n,r;
for(int i=0;i<20;i++)//初始化数组
{
charac[i]='A'+i;
}
cin>>n>>r;
cout<<n<<"=";
convert(n,r);
cout<<"(base"<<r<<")";
return 0;
}
void convert(int n,int r)
{
if(n==0)return;//递归出口
int m=n%r;//余数
if(m<0) //余数小于0,将n+基数,再取余
{
m=m-r;
n=n+r;
}
convert(n/r,r);
//需要将结果倒序输出,所以先递归后输出。
if(m>9)
cout<<charac[m-10];
else
cout<<m;
}