负进制转换

题目描述

以前我们做的进制转换大家都忽略了一点,就是进制一定是正整数;今天这道进制转换就坑爹的选择了,额,负整数来做进制。

输入

输入由若干行组成,每行有两个整数n(-32765<=n<=32767)和R(-16<=R<=-2)。输入的最后一行只有一个‘#’号,表示输入结束。

输出

对于每个输入行,输出n的R进制形式。出现的字母请用大写字母表示!

样例输入

 30000 -2
-20000 -2
28800 -16
-25000 -16
#
样例输出

 11011010101110000
1111011000100000
19180
7FB8
提示

来源

Neuq  Oj  http://ncc.neuq.edu.cn/oj/problem.php?id=1105

1.问题分析

     一般情况下,我们在做进制转换时,是利用除法来运算,同样的,在进制为负数的时候,应该也是这样的原理。

先举个例子,将10转换成2进制:

   商   余数

2| 10    

2|  5    0

2|  2    1

2|  1    0

2|  0    1            这样结果就是1010了

那么,再将10转换成-2进制就应该是这样了:

   商   余数             始终记住余数只能是0或者1

-2|  10    

-2|  -5    0

-2|   3    1   (正常情况下这一步应该是商为2,余数为-1,但是余数应为正,所以商+1)

-2|  -1    1

-2|   1    1   (这一步也是)

-2|   0    1    

这样结果就是11110      [ 1*(-2)4+1*(-2)3+1*(-2)2+1*(-2)1+0*(-2)0=16-8+4-2+0=10]

同理,其他情况下也是这样,具体数学证明过程我就不写了= =(其实是不会写)

2.我那弱弱的代码

#include<iostream>
#include<string.h> 
#include<cstdio>
using namespace std;
int mod_s(int a,int b)
{
  int s,y;
  s=a/b;
  y=a%b;
  if(a<0&&b<0)
   {
    if(y!=0)
     {s=s+1;y=a-b*s;}
    else if(y==0)
     {s=s;y=y;}
   }
  else
   {s=s;y=y;}
  return(s);
}
int mod_y(int a,int b)
{
  int s,y;  
  s=a/b;
  y=a%b;
  if(a<0&&b<0)
   {
    if(y!=0)
     {s=s+1;y=a-b*s;}
    else if(y==0)
     {s=s;y=y;}
   }
  else
   {s=s;y=y;}
  return(y);
}
int main()
{
  int N,C,i,l,j,k,m,nn[1000],cc[1000],n,c;
  k=0;
  while(scanf("%d%d",&N,&C)==2)
  {
       nn[k]=N;
       cc[k]=C;
       k++;
  }
  for(m=0;m<k;m++)
  { n=nn[m];
    c=cc[m];
    char a[1000];
    for(i=0;i>=0;i++)
      { if(0<=mod_y(n,c)&&mod_y(n,c)<=9)
          {a[i]=mod_y(n,c)+48;}
        else
          {a[i]=mod_y(n,c)+55;}
        if (mod_s(n,c)==0)
           {break;}
        n=mod_s(n,c);    
      }
    l=strlen(a);
    for(j=l-1;j>=0;j--)
     {cout<<a[j];}
    cout<<endl;
    for(j=l-1;j>=0;j--)
     {a[j]=NULL;}    
  }
  return 0;
}

--------------------- 
作者:cq857174940 
来源:CSDN 
原文:https://blog.csdn.net/coffin5257/article/details/8228200?utm_source=copy 
版权声明:本文为博主原创文章,转载请附上博文链接!

普通基数为正的进制转换中使用的都是短除法,即不断的除以基数取整,把所有的余数倒序输出就是转换完成之后的数了

但是对于基数为负数的进制转换,由于C/C++中模运算(%)的特性,余数可能为负,当然不能简单的取绝对值了事。

-5%-2=-1
网上找到了相关的处理方法,在此记录一下: 
在对负基数进制进行转换时,如果取模余数为正,那么就一切和正基数进制转换时一样 
但是当出现余数为负时,进行如下操作:

将计算出的商加1
n = n/k+1;  //n是原进制的数,在求解过程中会不断改变,k代表要转换为k进制
1
利用新的商乘以基数,再用被除数去减去这个结果,这样就可以得到一个正数
n-(n/k+1)*k
1
使用这个结果当作余数继续进行求解即可

/*输入要转换的数和要转换为几进制*/
#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>

using namespace std;

char toChar[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'};

int mod(int n, int k){
    if(n%k < 0)
        return n-(n/k+1)*k;
    else
        return n%k;
}

int main(){
    int n, k;
    string ans;

    while(cin>>n>>k){
        ans = "";
        cout<<n<<"=";
        while(n){
            ans = ans + toChar[mod(n, k)];
            if(n%k < 0)
                n = n/k+1;
            else
                n /= k;
        }

        reverse(ans.begin(), ans.end());
        cout<<ans<<"(base"<<k<<")"<<endl;
    }
    return 0;
}
--------------------- 
作者:AutumnBloods 
来源:CSDN 
原文:https://blog.csdn.net/AutumnBloods/article/details/79437966?utm_source=copy 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/liangjiubujiu/article/details/83091193