十进制数转换为负进制数


一、相关题目

洛谷 P1017 [NOIP2000 提高组] 进制转换


二、问题描述

输入一个十进制数n和一个负进制数的基数R,输出转换后的负进制数。


三、原理分析

十进制数转换为负进制数与十进制数转换为正进制数的原理相同。 我们需要不断用所给数除基数,获得一个余数,这个余数摆在最后一位,然后用商除基数再得新的商和余数,并不断将余数放在前一位,直到商为0。最终得到的这样一个由余数组成的数便是我们所需的答案。

有些人编程运算发现怎么也得不到正确答案,那是因为,这样转换的前提是我们每次得到的余数是一个正数或0,而根据c++和java的特性,对负数取模时向零取整(使商绝对值尽可能小),这使得我们可能得到一个小于0的余数。

例如:-15%-2==-1,商为7 && 15%-2==1,商为-7
而不是-15%-2==1,商为8 && 15%-2==-1,商为-8,因为上面行商的绝对值更小


四、算法解析

我们可以将取模的式子表示为如下形式

n=aR+b,a为商,b为余数

此时,如果b<0,根据取余运算的性质,将会有以下关系

R<b<0,由此得到 b-R>0

从而我们在n=aR+b中将a借出一位,得到

n=(a+1)R+b-R

这时我们得到的商变为了a+1,余数变为了b-R,可以满足余数大于0的要求。所以我们只需对每次算出的余数进行判断,若小于0,就令余数减去基数,除去基数得到的商再加1,否则按正常的方法转换。


五、代码实现(c++)

while(n!=0)
	{
		int b;//b为余数
		b=n%R;
		if(b<0)
		{
			ans=getnum(b-R)+ans;
			n=n/R+1;
		}
		else
		{
			ans=getnum(b)+ans;
			n/=R;
		}
	}
printf("%d=%s(base%d)",num,ans.c_str(),R);

压缩后完整代码

#include<iostream>
using namespace std;
int n,R;
std::string ans="";
inline char getnum(int x)
{
	return x<10?x+'0':(x-10)+'A';
}
int main()
{
	scanf("%d%d",&n,&R);
	int num=n;
	while(n!=0)
		n%R<0?(ans=getnum(n%R-R)+ans,n=n/R+1):(ans=getnum(n%R)+ans,n/=R);
	printf("%d=%s(base%d)",num,ans.c_str(),R);
	return 0;
}
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值