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

文章介绍了如何进行负基数的进制转换,通过数学公式解析了负数在负基数系统中的表示,并提供了处理负余数的借位规则。以-15转换为-2进制为例,展示了具体的操作步骤,最后给出了C语言的代码实现。

《编程思维与实践》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+kn1(R)n1+...+k0=[kn(R)n1+kn1(R)n2+...+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)=-15%(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)+(Rr) ,

则通过逆过程求出的特殊情况下的 kik_iki 应该为 R−rR-rRr , 下一位的 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<Rprpr1...p1qsqs1...q1=q0p0<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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值