洛谷:1017进制转换
我们可以用这样的方式来表示一个十进制数: 将每个阿拉伯数字乘以一个以该数字所处位置为指数,以 1010 为底数的幂之和的形式。例如 123123 可表示为 1×10^2+2× 10^1+3×10^0 这样的形式。
与之相似的,对二进制数来说,也可表示成每个二进制数码乘以一个以该数字所处位置为指数,以 22 为底数的幂之和的形式。
一般说来,任何一个正整数 RR 或一个负整数 -R−R 都可以被选来作为一个数制系统的基数。如果是以 RR 或 -R−R 为基数,则需要用到的数码为 0,1,....R-10,1,....R−1。
例如当 R=7R=7 时,所需用到的数码是 0,1,2,3,4,5,60,1,2,3,4,5,6,这与其是 RR 或 -R−R 无关。如果作为基数的数绝对值超过 1010,则为了表示这些数码,通常使用英文字母来表示那些大于 99 的数码。例如对 1616 进制数来说,用 AA 表示 1010,用 BB 表示 1111,用 CC 表示 1212,以此类推。
在负进制数中是用 -R−R 作为基数,例如 -15−15(十进制)相当于 110001110001 (-2−2进制),并且它可以被表示为 22 的幂级数的和数:
110001=1×(-2)^5+1×(-2)^4+0× (-2)^3+0× (-2)^2+0×(-2)^1 +1× (-2)^0
设计一个程序,读入一个十进制数和一个负进制数的基数, 并将此十进制数转换为此负进制下的数。
我的方法中做负进制转换共有两步。
一:用短除法像处理正常进制一样将所有余数算出来。例如(20)转换为-9进制,短除法算出来就是-22。然后我们逆推一下,-2*(-9)^1+2*(-9)^0=18+2=20;可以知道对于所有的进制和数都可以这样转换,只是出现了负数不符合逻辑。
二:从低位到高位逐一处理(x为某一位,r为基)。若x<0,x=x-r,x下一位加一;若x==-r,x=0,x下一位减一。
用(-2)进制举例吧,权重分别是(-8,4,-2,1)。对于第一种情况可以想象成x对结果的贡献值为负,而负进制的相邻位的权符号相反,只需要让比他大的一位加一,此位再减一个一样的数,那么结果自然不变,只是减去的数在此位表现为加上(-r)。比如第二位是-1,那么第三位先加1,就相当于加4,要使结果不变就需要减4,那就是-(-2)*(-2)。
对于第二种情况就是x的贡献已经溢出,将当前位的数减掉恰好可以抵消下一位的一个1。
#include<iostream>
using namespace std;
void f(int n,int r,int pr)
{
if (!n && !pr)
return;
int num = n % r + pr;
pr = 0;
if (num < 0) {
num = num - r;
pr = 1;
}
if (num == -r) {
num = 0;
pr=- 1;
}
f(n/r, r, pr);
if (num >= 10)
cout << char('A' + (num - 10));
else
cout << num;
}
int main()
{
int n, r, i = 0;
cin >> n >> r;
cout << n << '=';
f(n, r, 0);
printf("(base%d)", r);
return 0;
}