JavaSE基础(九)--Java二进制运算

Java二进制运算

Java二进制表示法

首先了解下二进制,二进制是相对十进制而言的,当然还有八进制,十六进制等等,我们常用的都是十进制,计算机用的都是二进制,而符号表示常用十六进制。

二进制就是只有0、1两个值表示的数,规则是逢二进一。数据存储在内存中都是存储的二进制,二进制又可分为原码、反码、补码。最终存储在内存中的是“补码”。

在了解原码、反码、补码之前先得了解一下机器数和真值。

机器数

一个数在计算机中的二进制表示形式,叫做这个数的机器数。机器数是带符号的,在计算机用机器数的最高位存放符号,正数为0,负数为1。比如,十进制中的数 +3 ,计算机字长为8位,转换成二进制就是 0000 0011。如果是 -3 ,就是 100 00011 。那么,这里的 0000 00111000 0011 就是机器数。

机器数的真值

因为第一位是符号位,所以机器数的形式值就不等于真正的数值。 例如上面的有符号数 1000 0011,其最高位1代表负,其真正数值是 -3,而不是形式值131(1000 0011转换成十进制等于131)。

所以,为区别起见,将带符号位的机器数对应的真正数值称为机器数的真值。例:0000 0001的真值 = +000 0001 = +1,1000 0001的真值 = –000 0001 = –1。

原码、反码、补码是计算机中对数字的二进制表示方法。一个正数的原码、反码、补码都是它的二进制表现形式。(无符号数没有原码、反码和补码一说。只有带符号数才存在不同的编码方式。)

原码、反码、补码

原码原码就是符号位加上真值的绝对值,即用第一位表示符号,其余位表示值。比如:如果是8位二进制:[+1]原 = 0000 0001, [-1]原 = 1000 0001;

反码:如果是正数,则表示方法和原码一样;如果是负数,符号位不变,其余各位取反,则得到这个数字的反码表示形式。比如:[+1]  = [0000 0001]原 = [0000 0001]反 ,[-1]  = [1000 0001]原 = [1111 1110]反;

补码:如果是正数,则表示方法和原码一样;如果是负数,则将数字的反码加上1(相当于将原码数值位取反然后在最低位加1)。

比如:[+1] = [0000 0001]原 = [0000 0001]反 = [0000 0001]补, [-1] = [1000 0001]原 = [1111 1110]反 = [1111 1111]补。

示例:

数值       原码         反码         补码
  6      0000 0110        0000 0110           0000 0110
 -6          1000 0110        1111 1001                     1111 1010
示例中均为8-bit的整数。它的可表示范围包括-128到127,总共256(=2<sup>8</sup>)个整数。0的反码、补码都为0。

进制转化

数学中的进制转化

十进制转二进制,整数部分除以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

Java内置的进制转换

用途 方法
十进制转成十六进制 Integer.toHexString(int i)
十进制转成八进制 Integer.toOctalString(int i)
十进制转成二进制 Integer.toBinaryString(int i)
十六进制转成十进制 Integer.valueOf("FFFF", 16).toString()
八进制转成十进制 Integer.valueOf("2234", 8).toString()
二进制转成十进制 Integer.valueOf("0110", 2).toString()

二进制位运算

1. 按位与(&)

位运算实质是将参与运算的数字转换为二进制,而后逐位对应进行运算。

按位与运算为:两位全为1,结果为1,即1&1=1,1&0=0,0&1=0,0&0=0。

例如51 & 5 -> 00110011 & 00000101 = 00000001 -> 51 & 5 = 1

特殊用法:

(1)与0相与可清零。

(2)与1相与可保留原值,可从一个数中取某些位。例如需要取10101110中的低四位,10101110 & 00001111 = 00001110,即得到所需结果。

2. 按位或(|)

两位只要有一位为1,结果则为1,即1|1=1,1|0=1,0|1=1,0|0=0。

特殊用法:

(1)与0相或可保留原值。

(2)与1相或可将对应位置1。例如,将X=10100000的低四位置1,使X | 00001111 = 10101111即可。

3. 异或运算(^)

两位为“异”,即一位为1一位为0,则结果为1,否则为0。即1^1=1,1^0=0,0^1=0,0^0=1。

特殊用法:

(1)使指定位翻转:找一个数,对应X要翻转的各位为1,其余为0,使其与X进行异或运算即可。例如,X=10101110,使低四位翻转,X ^ 00001111 = 10100001。

(2)与0相异或保留原值。例如X ^ 00000000 = 10101110。

(3)交换两变量的值。(比借助容器法、加减法效率高)原理:一个数对同一个数连续两次进行异或运算,结果与这个数相等。

因此,交换方法为:A = A ^ B,B = A ^ B,A = A ^ B。

4. 取反(~)

将一个数按位取反,即~ 0 = 1,~ 1 = 0。

5. 左移(<<)

将一个数左移x位,即左边丢弃x位,右边用0补x位。例:11100111 << 2 = 10011100。

拓展:

  • 原码:一个整数按照绝对值大小转换为二进制即为原码;
  • 反码:将二进制数按位取反,得到的即为反码;
  • 补码:反码加1即为补码。
  • 由于计算机底层硬件的限制,负数均使用补码表示。若左移时舍弃的高位全为0,则每左移1位,相当于该数十进制时乘一次2。

例:11(1011) << 2 = 44(11表示为1011时实际上不完整,若计算机中规定整型的大小为32bit,则11的完整二进制形式为00000000 00000000 0000000 00001011)

6. 右移(>>)

将一个数右移若干位,右边舍弃,正数左边补0,负数左边补1。每右移一位,相当于除以一次2。

例:4 >> 2 = 1,-14 >> 2 = -4。

7. 无符号右移(>>>)

将一个数右移若干位,左边补0,右边舍弃。

例:-14 >>> 2 = (11111111 11111111 11111111 11110010) >>> 2 = (00111111 11111111 11111111 11111100) = 1073741820

猜你喜欢

转载自www.cnblogs.com/fzsz086/p/11964536.html