进制转换题目解析

一、题目描述

我们可以用这样的方式来表示一个十进制数: 将每个阿拉伯数字乘以一个以该数字所处位置的(值减1)为指数,以10为底数的幂之和的形式。例如:123可表示十进制为1x10^2+2x10^1+3x10^0这样的形式。 与之相似的,对二进制数来说,也可表示成每个二进制数码乘以一个以该数字所处位置的(值-1)为指数,以2为底数的幂之和的形式。一般说来,任何一个正整数R或一个负整数-R都可以被选来作为一个数制系统的基数。如果是以R或-R为基数,则需要用到的数码为 0,1,….R-1。例如,当R=7时,所需用到的数码是0,1,2,3,4,5和6,这与其是R或-R无关。如果作为基数的数绝对值超过10,则为了表示这些数码,通常使用英文字母来表示那些大于9的数码。例如对16进制数来说,用A表示10,用B表示11,用C表示12,用D表示13,用E表示14,用F表示15。 在负进制数中是用-R作为基数,例如-15(十进制)相当于110001(-2进制),并且它可以被表示为2的幂级数的和数:

110001=1(-2)^5+1(-2)^4+0*(-2)^3+0*(-2)^2+0*(-2)^1+1*(-2)^0

设计一个程序,读入一个十进制数和一个负进制数的基数,并将此十进制数转换为此负进制下的数:-R∈{-2,-3,-4,…,-20}。

输入

每个测试文件只包含一组测试数据,每组输入两个整数,第一个是十进制数N(-32768<=N<=32767);第二个是负进制数的基数-R。

输出

对于每组输入数据,输出此负进制数及其基数,若此基数超过10,则参照16进制的方式处理。

输入样例1

3000 -2

输出样例1

30000=11011010101110000(base-2)

二、问题分析

涉及知识点: - 十进制数转化成二进制或者八进制或者16进制。 - 短除法。 - 数字的求模取余。

注意:一个负数表示成二进制的方法可以先求它相反数的二进制数,然后取反码,最后取补码,所得结果就是负数的二进制形式。不知道什么是原码、补码、反码的不要紧与解本题没有太大关系。

比较难为人的事情是,题目中介绍了什么是二进制与十六进制,但要我们求解一个负二进制到负二十进制。

简单介绍一下什么是短除法 短除法是十进制转换成任意进制形式的计算方法。十进制数转换成任意进制只要用短除法除对应的码数就行了,比如,十进制数1500转换成二进制形式应该用短除法除2,如果要转成十六进制那应该短除16,转成二十进制应该短除20。 十进制数13转换成二进制的计算过程:

2  |__13__  1
  2  |__6__  0
    2  |__3__  1
              1

所以13的二进制形式是1101,注意要从下往上写。 短除法右边的值是余数,13除2等6余1。

十进制数-15转换成负二进制的计算过程: 这个过程需要特别注意!

错误的运算:

  -2  |__-15__  -1
                 7
-1 = -15-(-2x7)
发现短除右边余数是-1,显然错了,二进制形式余数只能为0或1,同理十六进制余数只能为0~15
正确的运算:余数为负数时,商应该+1,使得余数不为负数。


  -2  |__-15__  1
     -2  |__8__  0
       -2  |__-4__  0
         -2  |__2__  0
            -2  |__-1__  1
                         1


1 = -15-(-2x8) = -15+16
0 = 8-(-2x-4)
0 = -4-(-2x2)
0 = 2-(-2x-1)
1 = -1-(-2x1)

所以-15的负二进制为110001。 多问就会了。

所以我们把要做的事情分为以下几步: - 首先进行求模运算,判断余数是否为负数 - 如果余数为负数,则商+1,再求余数,把余数记录下来 - 如果余数不为负数,正常求模运算,把余数记录下来

为了方便转换,定义一个字符数组charList,用于十六进制往后余数对应的字母A、B~F。

Java代码实现:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();// 手动输入
        int base = sc.nextInt(); // 手动输入
        int num_copy = num;
        int quotient = 0;// 商
        List<Character> list = new ArrayList<>();// 动态数组来存,因为不知道转换后有几位
        char[] charList = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
                'I', 'J' };
        while (num != 0) {
            int mod = num % base;
            if (mod < 0) {
                quotient = num / base + 1;
                mod = num - quotient * base;
                list.add(charList[mod]);
                num = quotient;
            }else{
                mod = num % base;
                num /= base;
                list.add(charList[mod]);
            }

        }
        Collections.reverse(list);//数组倒序
        StringBuilder sb = new StringBuilder(256);
        for (int i = 0; i < list.size(); i++) {
            sb.append(list.get(i));
        }
        System.out.println(num_copy+"="+sb.toString() + "(base" + base + ")");
        sc.close();
    }
}

C代码实现:

#include <stdio.h>
#include <stdlib.h>
int main() {
    int num = 0;
    int base = 0;
    scanf("%d", &num);   //手动输入
    scanf("%d", &base);  //手动输入
    int num_copy = num;
    int quotient = 0;  // 商

    char *list;  // C语言中的动态数组
    list = (char *)malloc(256 * sizeof(char));
    char charList[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                       'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'};

    int i = 0;  //计数器
    while (num != 0) {
        int mod = num % base;
        if (mod < 0) {
            quotient = num / base + 1;
            mod = num - quotient * base;
            list[i] = charList[mod];
            num = quotient;
            i++;
        } else {
            mod = num % base;
            num /= base;
            list[i] = charList[mod];
            i++;
        }
    }

    int k = 0;
    printf("%d=", num_copy);
    for (int i = 256; i >= 0; i--) {
        if (list[i] == NULL) {
            continue;
        }
        printf("%c", list[i]);
    }
    printf("(base%d)", base);
    return 0;
}