黑马程序员:查表法解决进制转换

---------------------- ASP.Net+Unity开发 .Net培训、期待与您交流! ----------------------

本文将用程序代码分析如何将十进制转换为二进制,八进制,十六进制。

首先,分析一下进制转换的方法。

一、十进制转换为二进制:

转换方法:十进制整数转换为二进制整数采用"除2取余,逆序排列"法。具体做法是:用2整除十进制整数,可以得到一个商和余数;再用2去除商,又会得到一个商和余数,如此进行,直到商为0时为止,然后把先得到的余数作为二进制数的低位有效位,后得到的余数作为二进制数的高位有效位,依次排列起来。

举例:给定十进制数“173”,转换为二进制数

图解:

十进制173转换为二进制

程序实现:

	public static String toBinary(int num){
		StringBuffer sb = new StringBuffer();
		while(num > 0){
			sb.append(num%2);
			num = num/2;
		}
		return sb.reverse().toString();
	}

二、十进制转换为八进制

转换方法:与二进制类似,只是八进制的基数为8,除8取余。把上图中的2换成8,可计算得出173的八进制值为“255”。

程序实现:

	public static String toBa(int num){
		StringBuffer sb = new StringBuffer();
		while(num > 0){
			sb.append(num%8);
			num = num/8;
		}
		return sb.reverse().toString();
	}
三、十进制转换为十六进制
转换方法:同上。只是十六进制有一个特殊,十六进制数总共有:0~15,逢十六进1。但是大于9的数,不能用数字表示,要用字母表示。10~15对应的是A、B、C、D、E、F。所以在使用十进制数除16时,如果余数大于9,那么就转换成字母。该转换方法为:(余数-10 + 'A')。
程序实现:我们分析得知,整型数据(int)是32位的。每一位十六进制数用4个二进制位表示,所以十进制转换为十六进制只需转换八次。num%16等价于num&15,num/16等价于num>>>4(右移四位),如下面的程序。
	public static String toHex(int num){
		StringBuffer sb = new StringBuffer(); //定义一个StringBuffer对象作为存储区域。
		for(int i=0;i<8;i++){
			int temp = num & 15; //定义一个中间变量temp,就收(num&15)的结果。(num & 15)等价于num%16
			if(temp > 9){ 
				//如果(num&15)的结果大于9,则需要转换为字母形式表示
				sb.append((char)(temp-10 + 'A')); 
			}else{
				sb.append(temp);
			}
			num = num >>> 4; //无符号右移四位
		}
		sb = sb.reverse();  //字符串反转操作
		/*
		 while循环去掉前面的0,例如:十进制的100,
		 转换成十六进制为“00000064”,经过这个while循环处理得到“64”。
		 从左到右去零,直到碰到一个非0.
		*/
		while(sb.length() > 0){
			if(sb.substring(0, 1).equals("0")){
				sb.deleteCharAt(0);
			}else{
				break;
			}
		}
		return sb.toString();
	}
通过分析,我们发现,与十六进制的转换类似,十进制转换为二进制时,(num%2)等价于(num&1),(num/2)等价于(num>>>1)。十进制转换八进制时,(num%8)等价于(num&7),(num/8)等价于(num>>>3)。所以,等到如下程序:
转二进制:
	public static String toBinary2(int num){
		StringBuffer sb = new StringBuffer();
		while(num > 0){
			sb.append(num&1);
			num = num>>>1;
		}
		return sb.reverse().toString();
	}
转八进制:
	public static String toBa2(int num){
		StringBuffer sb = new StringBuffer();
		while(num > 0){
			sb.append(num&7);
			num = num>>>3;
		}
		return sb.reverse().toString();
	}
我们发现上面程序中得出的结果都是反向的,必须使用StringBuffer的reverse方法进行转换。下面来进行优化一下。
上面程序中,我们直接使用了StringBuffer作为存储容器,下面我们使用另外一个容器——数组,来存储数据。要保证出来的结果不是反向的,我们要将指针定位在数组的末尾,逐一往前存储。使用查表法将上面的程序优化如下:
/**
 * 使用查表法实现十进制转换成二进制,八进制,十六进制的操作。
 * @author anjadeluo
 *
 */
public class DecimalConversion3 {

	/**
	 * 进制转换对照表:该表用于进制转换时,对相应的数进行查找。
	 * 该对照表中,包含了二进制数(0,1),八进制数(0~7),十六进制(0~9,A~F),并且每个数都对应着相应的下标。
	 * 数组的下标其实就是等于num&基数(二进制-1;八进制-7;十六进制-15)的值。
	 */
	public static char[] chs = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
	
	/**
	 * 进制转换。输入一个整数和转换方式,转换不同的进制
	 * @param num:待转换的数
	 * @param symbol:转换方式(二进制-2,八进制-8,十六进制-16)
	 * @return (返回对应进制数的字符串)
	 */
	public static String toXxx(int num ,int symbol){
		switch(symbol){
		case 2:
			return trans(num,1,1);
		case 8:
			return trans(num,7,3);
		case 16:
			return trans(num,15,4);
		default:
			return "暂无该进制";
		}
	}
	
	/**
	 * 进制转换的共通函数
	 * @param num:待转换的十进制数
	 * @param base:基数(二进制-1;八进制-7;十六进制-15)
	 * @param offset:偏移量(二进制-1;八进制-3;十六进制-4)
	 */
	public static String trans(int num ,int base ,int offset){
		StringBuffer sb = new StringBuffer();
		if(num == 0){
			sb.append(num);  //如果输入的整数是0,则返回0,直接结束。因为所有进制的0,都是0.
			return sb.toString();
		}
		char[] arr = new char[32]; //定义一个数组
		int pos = arr.length; //定义一个指针变量,用于指示进制数存放在数组中的位置,为了保证出来的结果非反向的,我们需要从数组末尾开始存储,所以指针定位在数组末尾。
		while(num != 0){
			int temp = num & base;  //待转换的整数与基数进行与运算。
			arr[--pos] = chs[temp];   //使用(num & base)的结果查表,得出的结果存放在数组中pos的位置。
			num = num >>> offset;  //待转换的整数无符号右移“偏移量”位
		}
		while(pos < arr.length){
			sb.append(arr[pos++]); //遍历数组,将有效数据存放到StringBuffer中。
		}
		return sb.toString();
	}

	public static void main(String[] args) {
		System.out.println(toXxx(173,2));
		System.out.println(toXxx(173,8));
		System.out.println(toXxx(173,16));
	}
}


----------------------  ASP.Net+Unity开发 .Net培训、期待与您交流! ----------------------

详细请查看:http://edu.csdn.net

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值