原创文章,转载请标注出处:《Java基础系列-二进制操做》java
Java源码中涉及到大量的二进制操做,很是的复杂,但很是的快速。布局
首先了解下二进制,二进制是相对十进制而言的,固然还有八进制,十六进制等等,咱们经常使用的都是十进制,计算机用的都是二进制,而符号表示经常使用十六进制。code
二进制就是只有0、1两个值表示的数,规则是逢二进一。ci
Java中使用补码来表示负数,具体就是除符号位以外,剩余位取反加1,符号位不变仍是1(符号位0-正数,1-负数)字符串
Java中二进制符号位也不是固定的,在Byte类型的数值中,因为其为一个字节即八位取值范围为-128到127,其符号位就是第8位二进制位。
以下所示:get
Byte型数据 1 -> 0000 0001 -1 -> 1111 1111(计算:1为00000001,-1为10000001,取反为11111110,加1为11111111) 127 -> 0111 1111 -127 -> 1000 0001(计算:127为01111111,-127为11111111,取反为10000000,加1为10000001) -128 -> 1000 0000(计算:128为100000000,取8位为00000000,-128为10000000,取反为11111111,加1为10000000)
Short型数为两个字节16位数值,其符号位为第16位:源码
Short型数据 1 -> 0000 0000 0000 0001 -1 -> 1111 1111 1111 1111(计算:1为0000000000000001,-1为1000000000000001,取反为1111111111111110,加1为1111111111111111) 32767 -> 0111 1111 1111 1111 -32767 -> 1000 0000 0000 0001(计算:32767为0111111111111111,-32767为1111111111111111,取反为1000000000000000,加1为1000000000000001) -32768 -> 1000 0000 0000 0000(计算:32768为10000000000000000,取16位为0000000000000000,-32768为1000000000000000,取反为1111111111111111,加1为1000000000000000)
Integer为32位,Long为64位,表示方式如上,Integer第32位为符号位,Long型第64位为符号位。it
Java中的浮点数大多数都没法精确表示,为何呢?由于使用二进制来表示小数同样存在和十进制表示小数同样的问题,存在无限循环的小数和无限不循环的小数,好比十进制的1/3,十进制为0.333...无限个3,二进制表示一样会有这个问题,二进制表示0.一、0.二、0.三、0.4等都不能精确表示,0.5能够表示为2^(-1),能够精确表示,可见只有能够精确的使用科学计数法表示的二进制小数才能精确表示,其余的一概没法精确表示。class
Java中使用32位的float和64位的double表示浮点小数。基础
Float型浮点数 格式:1位符号位,8位指数,23位尾数(S1_E8_M23) 符号位:0-正数,1-负数 指数位:采用移位存储,即用真实数值+127的二进制值来表示,好比,1要表示成128(即:10000000),128表示为255(即11111111) 尾数位:将十进制数转化为二进制以后,转化为科学计数法形式,取小数位做为尾数位,不足23位结尾补0 0.5 -> 0011 1111 0000 0000 0000 0000 0000 0000 (计算:0.5 = 1/2,即2^(-1),指数位为-1+127=126,即01111110,尾数为0,由于是正数,符号位为0) 10.5 -> 0100 0001 0010 1000 0000 0000 0000 0000 (计算:10的二进制为1010,0.5的二进制为0.1,因此10.5的二进制Wie1010.1,科学计数法表示为1.0101E11,如此一来,指数位为3+127=130,即10000010,符号位为0,尾数为0101,后面补0,够23位) 35.3 -> 0100 0010 0000 1101 0011 0011 0011 0011 (计算:35的二进制为100011,0.3的为二进制为0.01001100110011001100110011001100110011...,合起来就是100011.0100110011001100110011...,科学计数法为1.00011010011001100110011...E101,如此一来,符号位为0,指数位为5+127=132,即10000100,尾数为00011010011001100110011)
Double型浮点数 格式:1位符号位,11位指数,52位尾数 符号位:0-正数,1-负数 指数位:采用移位存储,用真是数值+1023的二进制值来表示,好比1要表示成1024(即:10000000000) 尾数位:将十进制转化为二进制,再转为科学计数法,取小数位做为尾数,不足52位结尾补0 35.3 -> 0100 0000 0100 0001 1010 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 (计算:35的二进制为100011,0.3的为二进制为0.01001100110011001100110011001100110011...,合起来就是100011.0100110011001100110011...,科学计数法为1.00011010011001100110011...E101,如此一来,符号位为0,指数位为5+1023=1028,即10000000100,尾数为0001101001100110011001100110011001100110011001100110)
进制转化:
十进制转二进制,整数部分除以2,整除为0,不然为1,直到结果为1,而后从后窜到前的结果就是其二进制值
好比:10 10/2 = 5 整除 0 5/2 = 2 未整除 1 2/2 = 1 整除 0 1 结果为1,结束 1 最后10的二进制值为:1010 再好比77 77/2=38 未整除 1 38/2=19 整除 0 19/2=9 未整除 1 9/2=4 未整除 1 4/2=2 整除 0 2/2=1 整除 0 1 结果为1,结束 1 最后77的二进制为1001101小数部分的二进制化,取小数部分乘以2,结果大于等于1,取1,不然取0,再取小数部分乘以2,取值,直到结果为0或者循环
好比:10.22 先进行整数部分二进制,结果为1010 再进行小数部分二进制: 0.22 * 2 = 0.44 0 0.44 * 2 = 0.88 0 0.88 * 2 = 1.76 1 0.76 * 2 = 1.52 1 0.52 * 2 = 1.04 1 0.04 * 2 = 0.08 0 0.08 * 2 = 0.16 0 0.16 * 2 = 0.32 0 0.32 * 2 = 0.64 0 0.64 * 2 = 1.28 1 0.28 * 2 = 0.56 0 0.56 * 2 = 1.12 1 0.12 * 2 = 0.24 0 0.24 * 2 = 0.48 0 0.48 * 2 = 0.96 0 0.96 * 2 = 1.92 1 0.92 * 2 = 1.84 1 0.84 * 2 = 1.68 1 0.68 * 2 = 1.36 1 0.36 * 2 = 0.72 0 0.72 * 2 = 1.44 1 ... 结果就是1010.00111000010100011110... 如果以科学计数法表示那就是1.01000111000010100011110...E11 如果表示成float的二进制形式那就是:0100 0001 0010 0011 1000 0101 0001 1110
与操做规则:全1为1,不然为0 例如: 1010 & 0101 = 0000 1111 & 0000 = 0000 1010 & 1111 = 1010 0101 & 0000 = 0000
扩展:二进制中的1的与操做具备保留原值的效果,任何值(0,1)和1进行与操做结果都不会变。这一点在HashMap中得以使用。
或操做规则:有1为1,全0为0 例如: 1010 | 0101 = 1111 1111 | 0000 = 1111 1010 | 1111 = 1111 0101 | 0000 = 0101
扩展:二进制中的0的或操做也具备保留原值的效果,任何值(0,1)和0进行或操做结果都不会变。
非操做规则:0为1,1为0 例如: ~1111 = 0000
异或操做规则:相同为0,不一样为1 例如: 1010 ^ 0101 = 1111 1111 ^ 0000 = 1111 1010 ^ 1111 = 0101 0101 ^ 0000 = 0101
扩展:二进制中的0的异或操做具备保留原值的效果,1的异或操做具备取反的效果。
左移规则:符号位保持不变的状况下剩余所有左移一位,低位补0,至关于乘以2的结果 例如: 0011 << 2 = 1100 1000 0000 1000 0001 << 2 = 1000 0010 0000 0100 (首位1为符号位)
右移规则:符号位保持不变的状况下剩余所有右移一位,高位补0,至关于除以2的结果 例如: 0011 >> 2 = 0000 1000 0000 1000 0001 >> 2 = 1000 0000 0010 0000 (首位1为符号位)
无符号右移规则:全员右移一位,高位补0,至关于除以2的结果 例如: 1000 0000 1000 0001 >> 2 = 0010 0000 0010 0000 (首位1为符号位)
参考例子中的操做:
public class BinaryTest { public static void main(String[] args){ int a = 100; String as = Integer.toBinaryString(a);// 整数的二进制表示,可输出二进制字符串 long b = 200; String bs = Long.toBinaryString(b);// 长整数的二进制表示,可输出二进制字符串 float c = 30.0f; int ci = Float.floatToIntBits(c);// 将浮点数的二进制布局解析为整型表示 int ci2 = Float.floatToRawIntBits(c);// 将浮点数的二进制布局解析为整型表示 float f2 = Float.intBitsToFloat(a);// 将整型数的布局解析为一个浮点数 double d = 302.22d; Long dl = Double.doubleToLongBits(d);// 将浮点数的二进制布局解析为长整型表示 Long dl2 = Double.doubleToRawLongBits(d);// 将浮点数的二进制布局解析为长整型表示 double d2 = Double.longBitsToDouble(b);// 将长整型数的布局解析为一个双精度浮点数 } }