进制的概念:通俗的讲就是逢几进一,拿我们最熟悉的十进制来说,每个位置最大数为9,例如个位到了9以后再加上1,就要向十位进一,个位就变成了0,单独看十位的1就代表10个单位1。百位的1就代表了1个10,而1个十位就代表了10个单位1,所以百位的1就代表了10x10个单位,往下继续推算,不难看出规律,第n个位置的数就代表了10的(n-1)次方个单位。其实对于其他进制都是同一个道理。

例如二进制:逢二进一


十进制

二进制

0

0

1

1

2

10

3

11

4

100

5

101

6

110


 

可以看出来二进制的表示方式很长,很不直观,所以我们人类的世界是不会直接使用二进制的。但是计算机比较笨,只认识0和1,为了和计算机好好沟通,我们只好学习下二进制,同时也要懂得其他进制的转换。我是通过黑马的教程来学习的,推荐给大家:

二进制:0-1,满2进1。

八进制:0-7,满8进1,用0开头表示,如:012。

十进制:0-9,满10进1。

十六进制:0-9,A-F,满16进1,用0x开头表示。如:0x4a2c。

 

任何数据在计算机中都是以二进制的形式存在的,二进制早期由电信号开关演变而来。一个整数在内存中一样也是二进制的,但是使用一大串的1或者0组成的数值进行使用很麻烦。所以就想把一大串缩短点,将二进制中的三位用一位表示。这三位可以取到的最大值就是7,超过7就进位了,这就是八进制。但是对于过长的二进制变成八进制还是较长,所以出现的用4个二进制位表示一位的情况,四个二进制位最大是15,这就是十六进制。

进制的基本转换

1. 十进制转二进制。

原理:对十进制数进行除2运算。

示例:求十进制数6的二进制数。

    6/2 = 3 余0

    3/2 = 1 余1

    1/2 = 0 余1

    故,6(十进制) = 110(二进制)。

 

2. 二进制转十进制。

原理:二进制乘以2的过程。

示例:求二进制数110的十进制数。

    110 = 0*2(0)+1*2(1)+1*2(2) = 0 + 2 + 4= 6

    附:括号中的数值代表次方。

示例:求二进制数00110101的十进制数。

      0   0  1   1   0   1   0   1

     128  64  32  16  8   4   2   1

   ------------------------------

    = 32 * 1 + 16 * 1 + 4 * 1+ 1 * 1 = 53

 

示例:二进制加法,5 + 4 = 9。

        1 0  1

    +  1 0  0

    ------------

   1   0  0  1

 3. 十进制转八进制。

原理:八进制,其实就是二进制位,3个二进制位,1个八进制位。

示例:求十进制数43的八进制数。

    十进制    43

    二进制    0101011

    三位分割 000-101-011

    八进制   0   5   3

    因此,43(十进制) =0101011(二进制) = 053(八进制)。

 

4. 十进制转十六进制。

原理:十六进制,其实就是二进制位,4个二进制位,1个十六进制位。

示例:求十进制数43的十六进制数。

    十进制    43

    二进制    0101011

    四位分割 0010-1011

    十六进制  2(2)- 11(B)

    因此,43(十进制) =0101011(二进制) = 0x2B(十六进制)

 

负数的进制

原理:负数的二进制表现形式就是对应的正数二进制取反加1。

示例:求-6的二进制表现形式,其实就是对应的正数6的二进制取反加1。

    取反    1111-1001

    加 1 + 0000-0001

    -------------------

                1111-1010     

 

 

 

下面介绍下在java中的位运算符

通过我自己写的几个小运算来解释下:

System.out.println(6&3);

  6-----110

&3-----011

-----------

            010------2

输出的结果为2

   

System.out.println(6|2);

  6-----110

| 2-----010

-----------

           110-----6

输出的结果为6

System.out.println(6^2);

   6-----110

^ 2-----010

-----------

            100-----4

 

输出的为4

System.out.println(6^2^2);

    6-----110

^ 2-----010      //这个地方是可以先运算2^2的,结果为0,任何与0进行^

^ 2-----010                  运算,结果还是其本身,道理想想就明白了

-----------

            110-----6

 

输出的结果为6

System.out.println(3<<1);

3是int类型的,占用4byte也就是4个8bit

00000000 00000000 00000000 00000011

根据规则左移1个单位

00000000 00000000 00000000 00000110

就是6,通过自己推算其中的原理,就可以发现左移一个就是乘以2

左移n,就是乘以2的n次方。只有自己推算才能更加理解。

同理,右移n,就是除以2的n次方。如下:

System.out.println(3>>2);

输出结果为0,因为3除以4取整为0;

System.out.println(-3>>>1);无符号右移

先把-3的补码写出来:(因为计算机中是补码存放的)

11111111 11111111 1111111111111101

右移一个,最高位补0,得到

01111111 11111111 1111111111111110

用科学计算器得:2147483646

 

 

通过例子可以更加深入的理解,但是还是需要自己动手去做,实践出真知。

 

 

补充一点:在程序编写过程中,尽量避免硬编码,要写成常量或者写入配置文件,而常见的乘以2和除以2的次方,我们就可以通过位移运算来解决,效率会更高。例如我们得到一个int变量b,当我们进行乘4后+1操作时,可以写成(b<<2)+1,这样的效率会更高,为什么要加括号呢?优先级的问题