《编程思维与实践》1016.负基数进制转换
题目


思路
注意到: N=kn(−R)n+kn−1(−R)n−1+...+k0=[kn(−R)n−1+kn−1(−R)n−2+...+k1]⋅(−R)+k0N=k_n(-R)^n+k_{n-1}(-R)^{n-1}+...+k_0=[k_n(-R)^{n-1}+k_{n-1}(-R)^{n-2}+...+k_1]·(-R)+k_0N=kn(−R)n+kn−1(−R)n−1+...+k0=[kn(−R)n−1+kn−1(−R)n−2+...+k1]⋅(−R)+k0 ,
其中ki>0(i=0,1...n)k_i>0(i=0,1...n)ki>0(i=0,1...n) , 则可以类似正整数基数的计算方式, 依次逆过程求出k0,k1...knk_0,k_1...k_nk0,k1...kn ,
但注意到对负数求余的结果可能为负数(如−5%(−2)=−1-5\%(-2)=-1−5%(−2)=−1) , 故需要对求余结果为负数的情况进行特殊处理(借位):
设 N%(−R)=−rN\%(-R)=-rN%(−R)=−r , 即 N=p⋅(−R)−r (r<R) ⟺ N=(p+1)⋅(−R)+(R−r)N=p·(-R)-r \,\, (r<R) \iff N=(p+1)·(-R)+(R-r)N=p⋅(−R)−r(r<R)⟺N=(p+1)⋅(−R)+(R−r) ,
则通过逆过程求出的特殊情况下的 kik_iki 应该为 R−rR-rR−r , 下一位的 NNN 对应变为 p+1p+1p+1.
这种负基数进制的表示是唯一的,可以类似平衡三进制的方法进行证明,
其中 prpr−1...p1−qsqs−1...q1=q0−p0<Rp_rp_{r-1}...p_1-q_sq_{s-1}...q_1=q_0-p_0<Rprpr−1...p1−qsqs−1...q1=q0−p0<R .
具体操作例子(-15转为-2进制):
-15/-2=7余-1,余数为负, -2×7-1=-15 等价于-2×8+1=-15,记录1;
8/-2=-4余0,记录0;
-4/-2=2余0,记录0;
2/-2=-1余0,记录0;
-1/-2=0余-1,余数为负,等价于-2×1+1=-1,记录1;
1/-2=0余1,记录1.
所以-15的-2进制表示为110001.
代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
int x,y;
scanf("%d%d",&x,&y);
char number[100];
int i=0;
do{
if(x%y>=0) //余数大于0,正常操作
{
if(x%y<10)
{
number[i]=x%y+'0';
}
else
{
number[i]=x%y+'A'-10;
}
x=x/y;
}
else //余数小于0,借位操作
{
if(x-y*(x/y+1)<10) // x/y+1 也就是 p+1, x-y*p(x/y+1)=R+r
{
number[i]=x-y*(x/y+1)+'0';
}
else
{
number[i]=x-y*(x/y+1)+'A'-10;
}
x=x/y+1;
}
i++;
}while(x!=0); //结束条件为x=0
for(int j=strlen(number)-1;j>=0;j--) //逆向输出
{
printf("%c",number[j]);
}
return 0;
}
文章介绍了如何进行负基数的进制转换,通过数学公式解析了负数在负基数系统中的表示,并提供了处理负余数的借位规则。以-15转换为-2进制为例,展示了具体的操作步骤,最后给出了C语言的代码实现。
3229

被折叠的 条评论
为什么被折叠?



