黑马程序员---Java基础之二:进制转换

------- android培训java培训java学习型技术博客、期待与您交流! ----------

一、进制的产生概述:

        我们的生活中,从小开始接触到的数学规则是满十进一,这就是进制的最常见制。在我们的世界里面,十进制是默认通用的,事实上其他进制在生活中我们也用不上。

在高速发展的现代社会,计算机浩浩荡荡地成为了人们生活中不可缺少的一部分,帮助人们解决通信联络,互动等各方面的问题。随着使用的人越来越多,计算机的世界也就越来越人们所了解。

在计算机中,数据储存是通过硬盘操作的,使用电路的形式来代表数据,电路里面的表现形式只有两种,开或者关,用0或者1来表示,这也就是二进制的起源了。

简单说,在人类的世界里面,十进制是通用的,在计算机的世界里面,二进制是通用的。在人类世界与计算机世界进行交流的过程中,就需要使用到翻译,这个翻译就是进制的转换了。在说明进制转换原理之前,先再说说我们还见过的常见的其他进制。

八进制: 满8进位,用数字0~7表示,在java中,用0开头表示 比如数字10用八进制表示就是: 012;

十六进制:满16进位,用数字0~9以及字母A~F表示,用0x开头 ,比如数字18在十六进制终究是:0xF2;

三十二进制:理论上有,但是因为代表的值太大了,所以基本上没有使用的情况。

那么,除了十进制和二进制的使用之外,其他几个进制的使用价值在哪里呢?下面解析进制的原理:

在计算机里面,最小的储存单位是字节byte,一个byte代表八个进制为:0000-0000。

比如我们定义一个byte a = 6 时,6这个数字在计算机里面的表现形式为: 0000-00110(使用其他类型的数据,可以使用多个byte来定义);这样就会产生一个问题,当这个数字很大的时候,显示这个数字所表示出来的字符长度就会很长,不便于阅读,于是就出现了常见的八进制,取三个进制为来表示一个数字,例如:

20的二进制表现形式为,0001-0100,如果使用八进制进行表示:00-010-100 , 则八进制的表现形式为:017 ,则看起来数字会更加的符合人类的认识度。

同理,十六进制也一样,使用4个进制位来表示一位。

至于为什么八进制和十六进制会和十进制一起出现,我个人的理解是:十进制是人类的规则,但是不完全符合计算机,八进制和十六进制是基于二进制的基础上做优化,相比起来转化的效率会更高。


二、进制的装换:

进制的转换就跟原理一样,满几进位,其中大致的规则如下:

其他进制到十进制

  • 其他进制包含二进制,八进制,十六进制
  • 转换规则
  • 先把数据的每一位上的系数乘以对应基数的次幂(低位从从零开始),然后相加即可
十进制到其他进制
  • 规则:除基取余,直到商为0,最后将余数反转
接下来详细分析一下进制是怎么进行装换的:

十进制--->二进制

对于整数部分,用被除数反复除以2,除第一次外,每次除以2均取前一次商的整数部分作被除数并依次记下每次的余数。另外,所得到的商的最后一位余数是所求二进制数的最高位。
对于小数部分,采用连续乘以基数2,并依次取出的整数部分,直至结果的小数部分为0为止。故该法称“乘基取整法”。
最常见的一个十进制,比如:6,如果将它转换成二进制数呢?
10进制数转换成二进制数,这是一个连续除以2的过程:
把要转换的数,除以2,得到商和余数,
将商继续除以2,直到商为0。最后将所有余数倒序排列,得到数就是转换结果。
听起来有些糊涂?结合例子来说明。比如要转换6为二进制数。
“把要转换的数,除以2,得到商和余数”。

那么,结合图片来看:

  1. 要转换的数是6, 6 ÷ 2,得到商是3,余数是0。
  2. “将商继续除以2,直到商为0……”现在商是3,还不是0,所以继续除以2。那就: 3 ÷ 2, 得到商是1,余数是1。
  3. “将商继续除以2,直到商为0……”          现在商是1,还不是0,所以继续除以2。那就: 1 ÷ 2, 得到商是0,余数是1
  4. “将商继续除以2,直到商为0……最后将所有余数倒序排列”好极!现在商已经是0。
  5. 我们三次计算依次得到余数分别是:0、1、1,将所有余数倒序排列,那就是:110了!
  6. 6转换成二进制,结果是110。
好了,那接下来,我们使用代码来实现将十进制转换为二进制:实现传入一个十进制参数,输出一个对应的二进制字符串,代码如下


public class ToBinary
{
	//实现传入一个整数,输出一个二进制的字符串
	public static void main (String [] args )
	{
		System.out.println(toBinaryString (134));
	}

	public static String toBinaryString(int num)
	{
		//定义一个字符串缓冲区,储存运算结果
		StringBuilder sb = new StringBuilder();
		while(num!=0)
		{
			//当num不等于0是,对num进行除2取模,将结果插入到字符缓冲区的第一位(等于是倒序排位结果)
			sb.insert(0,num%2);
			num = num>>1;
		}
		return sb.toString() ;
	}
}

运行的结果是:



十进制转换为二进制的步奏就是这样,同理,十进制转换为八进制和十六进制也是类似,下面代码实现了十进制转成其他进制的通用方法:

public class toBinary
{
	static char [] ch = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
	//实现传入一个整数,输出一个二进制的字符串
	public static void main (String [] args )
	{
		System.out.println(toOtherString (222));
		System.out.println(toOtherString (222,6));
		System.out.println(toOtherString (222,8));
		System.out.println(toOtherString (222,16));

	}

	public static String toOtherString(int num )
	{
		return toOtherString(num ,2);
	}
	public static String toOtherString(int num ,int regex)
	{
		//定义一个字符串缓冲区,储存运算结果
		StringBuilder sb = new StringBuilder();
		while(num!=0)
		{
			//当num不等于0是,对num进行除2取模,将结果插入到字符缓冲区的第一位(等于是倒序排位结果)
			//从对应的ch数组中,取出每个数字进制对应的字符,存入字符串缓冲区
			sb.insert(0,(char)ch[num%regex]);
			num = num/regex;
		}
		return sb.toString() ;
	}
}

运行结果是:



二进制转十进制:

二进制数第0位的权值是2的0次方,第1位的权值是2的1次方……
所以,设有一个二进制数:0110 0100,转换为10进制:
下面是竖式:
0110 0100 换算成十进制
第0位 0 * 20 = 0
第1位 0 * 21 = 0
第2位 1 * 22 = 4
第3位 0 * 23 = 0
第4位 0 * 24 = 0
第5位 1 * 25 = 32
第6位 1 * 26 = 64
第7位 0 * 27 = 0
公式:第N位2(N)
---------------------------
100
用横式计算为:
0 * 20 + 0 * 21 + 1 * 22 + 0 * 23 + 0 * 24 + 1 * 25 + 1* 26 + 0 * 27 = 100

同理的,八进制与十六进制的转换也一样,对应的位数乘以基数的对应位数的n次方,这样比较难理解,下面代码实现了将一个代表十六进制以下的数转换成10进制输出:

class ToShi 
{
	public static void main(String[] args) 
	{
		//打印不同进制下同一字符串代表的十进制的值
		System.out.println(toShi("11111",2));
		System.out.println(toShi("11111",8));
		System.out.println(toShi("11111",10));
		System.out.println(toShi("11111",16));
		System.out.println(toShi("A1F11",16));
		System.out.println(toShi("A1G11",16));
	}
	//输入一个数字的字符串形式,并输入注明这个字符串是多少进制的,最后将该字符串代表的数转换为十进制整数返回
	public static int toShi(String str,int regex)
	{
		//定义一个int类型的整数储存结果
		int sum = 0 ;
		for (int i = str.length()-1,j = 0;i>=0 ;i--,j++ )
		{
			char c = str.charAt(i);
			//判断,如果字母是大于A小于F的,则算出该字母代表的数字的值,然后值乘以进制基数的n次方,n等于该字母在字符串中的倒位位置
			if(c >= 'A'&&c <= 'F'&&regex==16)
			{
				int temp = (int)c -'A' +10;
				sum = sum + (int)(temp*Math.pow(regex,j));
			}else if (c >= '0'&&c <= '9')
			{
				int temp = (int)c -'0';
				sum = sum + (int)(temp*Math.pow(regex,j));
			}else{
				throw new RuntimeException("数字不合法,请输入十六进制内的数字");
				}
		}
		return sum;
	}
}

运行结果是:


负数的转换

负数在进行转换的时候根据,两个个步骤即可:

  1. 获取负数的补码形式,补码就是取反加1;
  2. 按照整数的转换形式进行转换即可。

个人小结:进制转换是比较基础的东西,很多人初学者都会忽视掉,特别是在实际开发中,都是使用Integer的toXXXString来进行快速的转换,更加不需要掌握实际的转换原理。但是我还是那句话,应对面试也好,实操也好。作为一个合格的程序,首先需要的尽可能的知道程序实现的原理,这样在需要开发的时候才会更得心应手。作为初学者,我希望从一开始就能有这样的习惯。


------- android培训java培训java学习型技术博客、期待与您交流! ----------

-------  android培训 java培训 java学习型技术博客、 期待与您交流! ----------
-------  android培训 java培训 java学习型技术博客、 期待与您交流! ----------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值