位移运算---为何负数不断地无符号向右移动的最小值是1呢?

简介: 位移运算---为何负数不断地无符号向右移动的最小值是1呢?

前言:

最近刚开始看《码出高效-Java开发手册》,看到位移运算这里发现了一个以前没有关注过的点,也就是博客标题,百思不解,经过一番搜索才真的了解了位移运算的实质。

我们知道位移符号一共有三种,左移<<、右移>>、无符号右移>>>


左移<<和右移>>


在左移<<和右移>>两种运算中,符号位均参与移动,除负数往右移动,高位补1之外,其他情况均在空位补0。


无符号右移>>>


当向右移动时,正负数高位均补0,正数不断向右移动的最小值是0,而负数不断向右移动的最小值是1。无符号意即藐视符号位,符号位失去特权,必须像其他平常的数字位一起向右移动,高位直接补0,根本不关心是正数还是负数。

先上代码看看:

public static void main(String[] args) {
    int num = -32,num1 = -64,num2 = 32;
    int a = num >> 33;
    int b = num >>> 31;
    int c = num1 >>> 64;
    int d = num1 >>> 63;
    int h = num1 >>> 65;
    int e = num2 >> 33;
    int f = num2 >>> 31;
    System.out.println("-32 >> 33:" + a);
    System.out.println("-32 >>> 31:" + b);
    System.out.println("-64 >>> 64:" + c);
    System.out.println("-64 >>> 63:" + d);
    System.out.println("-64 >>> 65:" + h);
    System.out.println("32 >>> 33:" + e);
    System.out.println("32 >>>> 31:" + f);

运算结果:

20191114221431580.png


这里我们可以重点看一下-64的无符号右移

20191114221645786.png


第一个问题:-64 >>> 64的结果是-64,不是说负数不断地无符号向右移动的最小值是1吗?

第二个问题:-64 >>> 63的结果是1,按照上面的说法似乎没有疑问,但是为什么呢???

第三个问题:-64 >>> 65的结果为什么那么大?


在实际编程中,位移运算仅作用于整型(32位)和长整型(64位)数上,假如在整型数上移动的位数是字长(同一时间处理二进制的位数)的整数倍,无论是否带符号以及移动方向,均为本身(这里解决了第一个问题)。


因为移动的位数是一个mod64的结果,即:对一个64位数进行无符号右移操作时,实际的位移为 位移值%64 也就是 >>>64 = >>>0,那么,一个64位数一次最大无符号右移值为63位,由于负数的第一位为-1,则-1XXX(63位X)>>>63 = 000(63个0)1。(这里解决了第二个问题)


而对于32位的数再说,无符号右移位数为 位移值%32 ,像short这种类型的数,在做位移之前,会先转为int类型,然后再进行转换。


那么,第三个问题的答案自行思考吧


这里还是举例补充说明一下吧,毕竟我也理解了很久

System.out.println("-16无符号右移2位:"+(-16>>>2));
//-16无符号右移2位:1073741820

这个是为什么?


首先一定要知道 无符号右移运算符>>> 只是对32位和64位的值有意义,这个在前面也说了


例如: -16的无符号右移2位应该这样算才对----------------------取32位长度的16的二进制补码加1

16二进制:00000000 00000000 00000000 00010000


补码+1后:11111111 11111111 11111111 11110000


右移两位高位补零:00111111 11111111 11111111 11111100

这个二进制对应的值就是1073741820

目录
相关文章
|
1月前
判断正数/负数
【10月更文挑战第18天】判断正数/负数。
31 6
|
12天前
|
Python
数值运算
数值运算。
22 4
|
3月前
|
C语言
用栈实现将一个十进制数值转换成八进制数值。即用该十进制数值除以8,并保留其余数;重复此操作,直到该十进制数值为0为止。最后将所有的余数反向输出就是所对应的八进制数值
这篇文章展示了如何使用栈(包括顺序栈和链栈)实现将十进制数值转换成八进制数值的方法,通过C语言编程演示了两种栈的实现方式和使用场景。
用栈实现将一个十进制数值转换成八进制数值。即用该十进制数值除以8,并保留其余数;重复此操作,直到该十进制数值为0为止。最后将所有的余数反向输出就是所对应的八进制数值
|
6月前
60.编程统计数组a中正数、0、负数的个数
60.编程统计数组a中正数、0、负数的个数
46 0
|
6月前
|
计算机视觉
浮点数向下取整
浮点数向下取整
39 0
|
6月前
|
Java
如何判断科学计数法3.14E+308 在区间3.14E+38和 3.14E+1308内
对于非常大的科学计数法表示的数值,直接将其转换为 `double` 类型可能会导致溢出。Java 中的 `double` 类型表示的最大值约为 `1.7976931348623157E+308`,因此 `3.14E+308` 已经超出了其表示范围。如果需要处理超出 `double` 类型表示范围的数值,可以使用 `BigDecimal` 类来处理。 以下是一个示例,展示如何使用 `BigDecimal` 类来比较科学计数法表示的数值是否在指定区间内: ```java import java.math.BigDecimal; public class ScientificNotationC
|
前端开发 JavaScript 程序员
数值的整数次方
数值的整数次方
数值的整数次方
输出最小的数位和等于x并且各个数位都不一样的值
输出最小的数位和等于x并且各个数位都不一样的值
47 0
|
人工智能
作业三——求左部分中的最大值减去右部分最大值的绝对值,最大是多少
给定一个长度为N(N>1)的整型数组A,可以将A划分成左右两个部分,左部分A[0..K],右部分A[K+1..N-1],K可以取值的范围是[0,N-2]。
882 0