住房城乡建设局网站首页,织梦网站图片修改不了,国外h5网站模板,wordpress 老萨我们知道计算机使用的是二进制#xff0c;我们⽤⼀个字节#xff0c;也就是8个bit 来表示⼆进制数。
原码
十进制 原码20000 0010-21000 0010
原码其实是最容易理解的#xff0c;只不过需要利⽤⼆进制中的第⼀位来表示符号位#xff0c;0表示正数#xff0c;1表示…我们知道计算机使用的是二进制我们⽤⼀个字节也就是8个bit 来表示⼆进制数。
原码
十进制 原码20000 0010-21000 0010
原码其实是最容易理解的只不过需要利⽤⼆进制中的第⼀位来表示符号位0表示正数1表示负数所 以可以看到⼀个数字⽤⼆进制原码表示的话取值范围是 -111 1111 ~ 111 1111 换成⼗进制就 是 -127 ~ 127 。
反码
对于计算机来说最好只有加法这样计算机会更加简单⾼效我们知道在数学中 5-32 其实可以转换成 5(-3)2 这就表示减法可以⽤加法表示⽽乘法是加法的累积除法是减法的累积所以在计算机中只要有加法就够了。 ⼀个数字⽤原码表示是容易理解的但是需要单独的⼀个bit来表示符号位。并且在进⾏加法时计算机需要先识别某个⼆进制原码是正数还是负数识别出来之后再进⾏相应的运算。这样效率不⾼能不能让计 算机在进⾏运算时不⽤去管符号位也就是说让符号位也参与运算这就要⽤到反码。
十进制 原码反码20000 00100000 0010-21000 00101111 1101
我们可以看到对于正数反码等于原码对于负数就是符号位保持不变其余各位对原码取反。那么我们来看⼀下⽤反码直接运算会是什么情况我们以 5-3 举例。
5 - 3 5-3
十进制 原码反码50000 01010000 0101-31000 00111111 1100
5-35(-3)0000 0101(反码) 1111 1100(反码)0000 0001(反码)0000 0001(原码)1
计算结果为1为什么差了1我们来看⼀个特殊的运算1-1
1-11(-1)0000 0001(反码) 1111 1110(反码)1111 1111(反码)1000 0000(原码)-000 运算如下
000000 0000(反码) 0000 0000(反码)0000 0000(反码)0000 0000(原码)0
从以上的运算中我们可以看到1000 0000表示-00000 0000表示0虽然-0和0是⼀样的但是在⽤原码和反码表示时 是不同的我们可以理解为在⽤⼀个字节表示数字取值范围时这些数字中多了⼀个-0所以导致我们在 ⽤反码直接运算时符号位可以直接参加运算但是结果会不对。
补码
为了解决上面的问题我们可以采用补码
十进制原码反码补码20000 00100000 00100000 0010-21000 00101111 11011111 1110
也就是说正数的补码和原码、反码⼀样负数的补码就是反码1。
十进制 原码反码补码50000 01010000 01010000 0101-31000 00111111 11001111 1101
采用补码后我们在来看5-3的执行过程
5-35(-3)0000 0101(补码) 1111 1101(补码)0000 0010(补码)0000 0010(原码)2
5-32结果真确。再来看一个特殊的1-1
1-11(-1)0000 0001(补码) 1111 1111(补码)0000 0000(补码)0000 0000(原码)0
继续00
000000 0000(补码) 0000 0000(补码)0000 0000(补码)0000 0000(原码)0
所以我们可以看到补码解决了反码的问题。 所以对于数字我们可以使⽤补码的形式来进⾏⼆进制表示。
位移运算
java中的位移运算有 左移 右移 ⽆符号右移
正数位移运算
System.out.println(2 1); // 4
System.out.println(2 1); // 1
System.out.println(2 1); // 1
System.out.println(-2 1); // -4
System.out.println(-2 1); // -1
System.out.println(-2 1); // 2147483647
乍⼀眼看到上⾯Demo的打印结果你应该是懵逼的接下来我来解释⼀下这个结果到底是如何运算出来的。
21 :⼗进制“2”转换成⼆进制为“00000000 00000000 00000000 00000010”再将⼆进制左移⼀位⾼位丢弃低位补0所以结果为“00000000 00000000 00000000 00000100”换算 成⼗进制则为“4”。一个数字左移N位相当于乘以2的N次方。
21: ⼗进制“2”转换成⼆进制为“00000000 00000000 00000000 00000010”再将⼆进制 右移⼀位低位丢弃⾼位补0所以结果为“00000000 00000000 00000000 00000001”换算 成⼗进制则为“1 。一个数右移N位相当于除以2的N次方。
对于这两种情况⾮常好理解那什么是⽆符号右移以及负数是怎么运算的呢 我们先来看 -2 1 这两个负数的左移与右移操作其实和正数类似都是先将⼗进制 数转换成⼆进制数再将⼆进制数进⾏移动所以现在的关键是负数如何⽤⼆进制数进⾏表示。
负数位移运算
我们再来看 -2 1 。 -2⽤原码表示为 10000000 00000000 00000000 00000010 -2⽤反码表示为 11111111 11111111 11111111 11111101 -2⽤补码表示为 11111111 11111111 11111111 11111110 -2 1 表示-2的补码左移⼀位后为 11111111 11111111 11111111 11111100 该补码对应 的反码为
11111111 11111111 11111111 11111100
- 111111111 11111111 11111111 11111011
该反码对应的原码为符号位不变其他位取反为 10000000 00000000 00000000 00000100 表示-4。 所以 -2 1 是⼀样的计算⽅法这⾥就不演示了。
⽆符号右移
上⾯在进⾏左移和右移时有一点需要注意就是在对补码进⾏移动时符号位是固定不动的⽽⽆符号 右移是指在进⾏移动时符号位也会跟着⼀起移动。 ⽐如 -2 1 。 -2⽤原码表示为 10000000 00000000 00000000 00000010 -2⽤反码表示为 11111111 11111111 11111111 11111101 -2⽤补码表示为 11111111 11111111 11111111 11111110 -2的补码右移1位为 01111111 11111111 11111111 11111111 右移后的补码对应的反码、原码为 01111111 11111111 11111111 11111111 因为现在的符号 位为0表示正数正数的原、反、补码都相同 所以对应的⼗进制为2147483647。 也就是 -2 1 2147483647
总结
这⾥总结⼀下我们可以发现 2 1 4 2*2
2 2 8 2*2*2
2 n 2*2 m n m * 2 右移则相反所以⼤家以后在源码中再看到位运算时可以参考上⾯的公式。