精华内容
下载资源
问答
  • ”与有符号右移“>>>” Java提供了两种右移运算符:“>>”和">>>"。其中,“>>”被称为有符号右移运算符,“>>>”被称为无符号右移运算符,它们的功能是将参与运算的对象...

    一、无符号右移“>>>”与有符号右移“>>”

    Java提供了两种右移运算符:“>>” 和">>>"。其中,“>>”被称为有符号右移运算符“>>>”被称为无符号右移运算符,它们的功能是将参与运算的对象对应的二进制数右移指定的位数。二者的不同点在于“>>”在执行右移操作时,若参与运算的数字为正数,则在高位补0;若为负数,则在高位补1。而“>>>”则不同,无论参与运算的数字为正数或为负数,在执运算时,都会在高位补0。

    此外,需要注意的是,在对char、byte、short等类型的数进行移位操作前,编译器都会自动地将数值转化为int类型,然后才进行移位操作。由于int型变量只占4Byte(32bit),因此当右移地位数超过32bit时,移位运算没有任何意义。所以,在Java语言中,为了保证移动位数地有效性,以使右移的位数不超过32bit,采取了取余的操作,即a>>n等价于a>>(n%32)。


    二、“<<”运算符与“>>”运算符

    "<<"运算符表示左移,左移n位表示原来的值乘2的n次方,经常用来代替乘法操作。例如,一个数m乘以16可以表示为将这个数左移4位(m<<4),由于CPU直接支持位运算,因此位运算比乘法运算效率高。

    与右移运算不同的是,左移运算没有有符号和无符号左移动,在左移时,移除高位的同时在低位补0

    与右移运算相同的是,当进行左移运算时,如果移动的位数超过了该类型的最大位数,那么编译器会对移动的位数取模,例如对int类型的数移动33位,实际上只移动了33%32=1位。


    展开全文
  • 一. 机器数和真值 在学习原码, 反码和补码之前, 需要先了解机器数和真值的概念. 1、机器数 一个数在计算机中的二进制表示形式, 叫做这个数的机器数。机器数是带符号的,在计算机用一个数的最高位...例如上面的有符号

    一. 机器数和真值

    在学习原码, 反码和补码之前, 需要先了解机器数和真值的概念.

    1、机器数
    一个数在计算机中的二进制表示形式, 叫做这个数的机器数。机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1.

    比如,十进制中的数 +3 ,计算机字长为8位,转换成二进制就是00000011。如果是 -3 ,就是 10000011 。

    那么,这里的 00000011 和 10000011 就是机器数。

    2、真值
    因为第一位是符号位,所以机器数的形式值就不等于真正的数值。例如上面的有符号数 10000011,其最高位1代表负,其真正数值是 -3 而不是形式值131(10000011转换成十进制等于131)。所以,为区别起见,将带符号位的机器数对应的真正数值称为机器数的真值。

    例:
    0000 0001的真值 = +000 0001 = +1,
    1000 0001的真值 = –000 0001 = –1
    原码, 反码, 补码的基础概念和计算方法.


    二.原码反码补码概念

    计算机中二进制相加逢二进一
    在探求为何机器要使用补码之前, 让我们先了解原码, 反码和补码的概念.对于一个数, 计算机要使用一定的编码方式进行存储. 原码, 反码, 补码是机器存储一个具体数字的编码方式.

    原码:

    原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值. 比如如果是8位二进制:

    [+1]原 = 0000 0001
    
    [-1]原 = 1000 0001
    

    第一位是符号位. 因为第一位是符号位, 所以8位二进制数的取值范围就是:

    [1111 1111 , 0111 1111

    [-127 , 127]

    原码是人脑最容易理解和计算的表示方式.

    反码

    反码的表示方法是:

    • 正数的反码是其本身

    • 负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.

    [+1] = [00000001]原 = [00000001]反

    [-1] = [10000001]原 = [11111110]反

    可见如果一个反码表示的是负数, 人脑无法直观的看出来它的数值. 通常要将其转换成原码再计算.

    补码

    补码的表示方法是:

    • 正数的补码就是其本身

    • 负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)

    [+1] = [00000001]原 = [00000001]反 = [00000001]补

    [-1] = [10000001]原 = [11111110]反 = [11111111]补

    对于负数, 补码表示方式也是人脑无法直观看出其数值的. 通常也需要转换成原码在计算其数值.


    三. 为何要使用原码, 反码和补码

    现在我们知道了计算机可以有三种编码方式表示一个数. 对于正数因为三种编码方式的结果都相同:

    [+1] = [00000001]原 = [00000001]反 = [00000001]补
    

    所以不需要过多解释. 但是对于负数:

    [-1] = [10000001]原 = [11111110]反 = [11111111]补
    

    那有了原码,为什么还需要补码和反码呢?为什么负数需要反码和补码的表示形式呢?
    计算十进制的表达式:1+1=2

    1 + 1 = [00000001]原 + [00000001]原 = [00000010]原 = 2 
    

    从上面来看十进制只是完成了两个正数的相加,但是看下面:

    计算十进制的表达式: 1-1=0

    1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 
    =  [10000010]原 = -2
    

    如果用原码表示, 让符号位也参与计算, 显然对于减法来说, 结果是不正确的.这也就是为何计算机内部不使用原码表示一个数.

    为了解决原码做减法的问题, 出现了反码:

    计算十进制的表达式: 1-1=0

    1 - 1 = 1 + (-1) 
    = [0000 0001]原 + [1000 0001]原
    = [0000 0001]反 + [1111 1110]反 
    = [1111 1111]反 
    = [1000 0000]原 = -0
    

    发现用反码计算减法, 结果的真值部分是正确的. 而唯一的问题其实就出现在"0"这个特殊的数值上. 虽然人们理解上+0和-0是一样的, 但是0带符号是没有任何意义的. 而且会有[0000 0000]原和[1000 0000]原两个编码表示0.

    于是补码的出现, 解决了0的符号以及两个编码的问题:

    1-1 = 1 + (-1) 
    = [0000 0001]原 + [1000 0001]原 
    = [0000 0001]补 + [1111 1111]补 
    = [0000 0000]补
    =[0000 0000]原
    =0
    

    这样0用[0000 0000]表示, 而以前出现问题的-0则不存在了.而且可以用[1000 0000]表示-128:

    (-1) + (-127) 
    = [1000 0001]原 + [1111 1111]原 
    = [1111 1111]补 + [1000 0001]补 
    = [1000 0000]补
    =-128
    

    -1-127的结果应该是-128, 在用补码运算的结果中, [1000 0000]补 就是-128. 但是注意因为实际上是使用以前的-0的补码来表示-128, 所以-128并没有原码和反码表示.(对-128的补码表示[1000 0000]补算出来的原码是[0000 0000]原, 这是不正确的)

    使用补码, 不仅仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数. 这就是为什么8位二进制, 使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127].

    因为机器使用补码, 所以对于编程中常用到的32位int类型, 可以表示范围是: [-231, 231-1] 因为第一位表示的是符号位.而使用补码表示时又可以多保存一个最小值.

    四.左移<<,右移>>,和无符号右移>>>

    根据上面的结论可以知道,计算机底层使用的是补码的方式进行运算的。

    计算十进制表达式:4/4=2

    //换成位移运算(右移两位相当于:4/(2*2))
    4/4 = 4>>2
    //转换成二进制补码运算(正数的原码反码补码相同),也就是4的二进制右移两位。
    =00000100[补]
    //正数右移后高位补零
    =00 000001
    //换算成十进制
    =1
    

    计算十进制表达式:-4/2=-2

    //换算成位运算
    -4/2 = -4>>2
    //转换成二进制补码运算(负数的补码:符号位不变,其余的取反然后加1)
    =10000100[原] = 11111100[补]
    //负数右移两位后高位补1,因为要保证符号为负 即1
    =11 111111[补]
    //负数得到运算后的补码需要转回原码然后转成十进制(符号位不变,然后取反+1)
    =10000001[原]
    //换算成十进制
    =-1
    

    计算十进制表达式:1*4=4

    //换算成位运算(左移两位相当于:1*(2*2))
    1*4 = 1<<2
    //转换成二进制补码运算
    =00000001[补]
    //左移两位低位补0
    =000001 00[补]
    //转换成十进制
    =4
    

    计算十进制表达式:-1*4=-4

    //换算成位运算
    -1*4 = -1<<2
    //换算成二进制补码运算
    =10000001[原] = 11111111[补]
    //左移两位低位补0
    =111111 00[补]
    //转换成原码(负数补码取反加1 = 原码)
    =10000100[原]
    //转换成十进制
    =-4
    

    无符号右移

    无符号右移,不论正负高位统一补0

    计算无符号右移:4>>>2

    4>>>2
    //换算成二进制补码运算
    =00000100[补]
    //开始右移两位
    =00000001[补]
    //换算成十进制
    =1
    

    计算无符号右移:-4>>>2

    -4>>>2
    //换算成二进制补码运算
    =10000100[原] = 11111100[补]
    //开始右移两位,无符号右移中无论正负高位统一补0
    =00111111[补]
    //换算成十进制,int类型是32位,以上举例统一用8位只是方便计算。
    =1073741823
    

    从上面的无符号运算来看,正数的无符号右移和带符号右移的结果是一样的,因为带符号右移的时候也是高位补0,负数在带符号右移的时候是高位补1的,所以负数得到的结果是不会相同的。

    展开全文
  • #include <vector> #include <iostream> #include <unordered_map> using namespace std; int main() { // 左移 unsigned int un_stringify = 0xa... "无符号左移:" << endl; // 10
    #include <vector>
    #include <iostream>
    #include <unordered_map>
    
    using namespace std;
    
    
    int main() {
        // 左移
        unsigned int un_stringify = 0xa0000000;
        int stringify = 0xa0000000;
    
        cout << "无符号左移:" << endl;
        // 1010 0000 0000 0000 0000 0000 0000 0000 = 2^31 + 2^29 = 2684354560
        cout << un_stringify << endl;
        // 0100 0000 0000 0000 0000 0000 0000 0000 = 2^30 = 1073741824
        cout << (un_stringify << 1) << endl;
        // 等价于左移1位
        cout << (un_stringify << 33) << endl;
        //1000 0000 0000 0000 0000 0000 0000 0000 = 2^31 = 2147483648
        cout << (un_stringify << 2) << endl;
        // 等价于左移2位
        cout << (un_stringify << 34) << endl;
    
        cout << "有符号左移:" << endl;
        // 1010 0000 0000 0000 0000 0000 0000 0000 这是原码 转换成补码是:1110 0000 0000 0000 0000 0000 0000 0000=-(2^30+2^29)=1610612736
        cout << (stringify) << endl;
        // 0100 0000 0000 0000 0000 0000 0000 0000 = 2^30 = 1073741824
        cout << (stringify << 1) << endl;
        // 等价于左移1位
        cout << (stringify << 33) << endl;
        // 1000 0000 0000 0000 0000 0000 0000 0000 = -2147483648,最小的负数
        cout << (stringify << 2) << endl;
        // 等价于左移2位
        cout << (stringify << 34) << endl;
    
        cout << "无符号右移:" << endl;
        // 1010 0000 0000 0000 0000 0000 0000 0000 = 2^31 + 2^29 = 2684354560
        cout << un_stringify << endl;
        // 0101 0000 0000 0000 0000 0000 0000 0000 = 2^30 + 2^28 = 1342177280
        cout << (un_stringify >> 1) << endl;
        // 等价于右移1位
        cout << (un_stringify >> 33) << endl;
        // 0010 1000 0000 0000 0000 0000 0000 0000 = 2^29 + 2^27 = 671088640
        cout << (un_stringify >> 2) << endl;
        // 等价于右移2位
        cout << (un_stringify >> 34) << endl;
    
        cout << "有符号右移:" << endl;
        // 1010 0000 0000 0000 0000 0000 0000 0000
        cout << stringify << endl;
        // 1101 0000 0000 0000 0000 0000 0000 0000 ,这是原码,转换成补码是-(2^29+2^28) = -805306368
        cout << (stringify >> 1) << endl;
        cout << (stringify >> 33) << endl;
        // 1110 1000 0000 0000 0000 0000 0000 0000 = ,这是原码,转换成补码是-(2^28+2^27) = -402653184
        cout << (stringify >> 2) << endl;
        cout << (stringify >> 34) << endl;
    
    
        return 0;
    }
    

    输出结果如下:

    无符号左移:
    2684354560
    1073741824
    1073741824
    2147483648
    2147483648
    有符号左移:
    -1610612736
    1073741824
    1073741824
    -2147483648
    -2147483648
    无符号右移:
    2684354560
    1342177280
    1342177280
    671088640
    671088640
    有符号右移:
    -1610612736
    -805306368
    -805306368
    -402653184
    -402653184
    

    总结:左移,不管对于有符号数还是无符号数,都是最低位补0,右移时,对于无符号,高位补0,对于有符号,高位都补符号位,并且,当数是负数时,对于有符号数,要转换成补码的形式

    展开全文
  • 如题,我看视频讲解说左移需要增加位数,但是书上举的例子并没有说要增加位数,我查论坛上两种说法,有点懵了。
  • 移位操作逻辑移位和算术移位 逻辑移位是不考虑符号位的移位,算术移位是考虑符号位的移位。 1、无符号移位 例如右移 unsigned char x = 0x80 二进制 表示是 1000 0000 ,十进制是128 右移动一位,低位补...

    移位操作有逻辑移位和算术移位

       逻辑移位是不考虑符号位的移位,算术移位是考虑符号位的移位。

    1、无符号移位

    例如右移

      unsigned char  x = 0x80 

       二进制 表示是  1000 0000  ,十进制是128

     右移动一位,低位补0 变为     0000 0000  ,十进制是 0

         unsigned char    x = 0x80;
         unsigned  char y = (x << 1);
         printf("%.2x\n", y );    

    输出  00H

      二进制表示 0000 0000  ,十进制 0

      这种情况是溢出了

     

    左移

     

      unsigned char  x = 0x80 

      左移动一位,高位补0 变为     0100 0000

         unsigned char    x = 0x80;
         unsigned  char y = (x >> 1);
         printf("%.2x\n", y );    

    输出  40

      二进制表示 0100 0000  ,十进制 64

     移位前是128 ,移位后是64,左移一位是除2

     

     

     

      

    转载于:https://www.cnblogs.com/snail88/p/7396337.html

    展开全文
  • 对于无符号数以及有符号数值左移效果一致,如: //默认i为32位 int i = 1; //i = 0000 0000 0000 0000 0000 0000 0000 0001 i = i << 31;//i = 1000 0000 0000 0000 0000 0000 0000 0000, i = -2147483648 ...
  • 位运算<<,>>,>>>讲解(应该算详细了) 使用位运算求整数绝对值之前我们...左移是没有有符号的这一点在说到左移是会说明。 可能有些朋友到这里有些蒙圈,什么是有符号?左右移又代表什么呢? ...
  • C_无符号数和有符号数的左移和右移

    万次阅读 2012-02-22 11:58:53
    今儿巩固下概念,转载下百度上找到的资料,加上了自己的理解,供参考 1 当左移移出的是“1”而不是0时,你该怎么想? 2 当左移的操作数是一个sign型是,你该怎么想?...6 兴趣的话可以研究一下单片机汇编中的循
  • 有符号左移<<总结有无符号 原码、反码、补码 正数 正数的原码、反码、补码都是该数字的二进制表示。 首先我们需要知道,计算机中的移位运算都是以二进制补码形式进行的,就像我们的Integer.toBinaryString(num...
  • 符号位右移详解
  • 计算机表示数字正负不是用+ -加减号来表示,而是用最高位数字来...1.有符号右移&amp;gt;&amp;gt;(若正数,高位补0,负数,高位补1) 正数:例如4&amp;gt;&amp;gt;2 首先写出4的二进制数,因为是正数...
  • 在众多语言中,都提供了关于位操作符,但为什么右移有“有无”符号之别,而左移却没有?,本文一步步讲述左移有符号右移、无符号右移,以此来揭开位移的面纱,最终探究答案
  • 普通的右移,都是在左边补0,那么对于一个负数最高位为1,又移后,左边符号位补0,这肯定是不对的,那么可以这样解决:对于有符号数,如果是正数,右移左边补0,如果是负数,右移左边补1,,这样可以解决。...
  • —— 有符号左移 >> —— 有符号右移 <<< —— 无符号左移 >>> —— 无符号右移 无符号移位(>>>)和有符号移位(>>)的区别是: 有符号位移运算时如果数字为正数时位移...
  • 而对于有符号数,其左移操作还是逻辑左移,但右移操作是采用逻辑右移还是算术右移就取决于机器了!(算术右移和逻辑右移的区别是:算术右移不右移符号位,即最高位,右移后前补0还是1取决于符号位的值;逻辑右移执行...
  • 此文皆为本人观点,不足的地方望指出! 左移位: 左移操作时将运算数的二进制码整体左移指定位数...无符号右移(注意:并没有无符号左移):>>> 无符号右移操作是将运算数的二进制码整体右移指定位数,右移之后的空位
  • java位运算,左移,右移,无符号右移

    千次阅读 2018-03-27 18:12:03
    指指定的值的所有位有左移 规定的次数1)格式: value &lt;&lt; num ; num要移动的次数规则:丢弃最高位,0补最低位注意:如果移动的次数,超过了该类型的最大位数,那么编译器会对移动的位数取模。如对int(4个...
  • 移位操作: ... 一个很有趣的误区是,认为符号位保持不变,仅仅移动数据位,这是不对的,因为无论数据位还是符号位,都是二进制,在整体大迁移的过程中,符号位也是要跟随潮流的。只不过,为了保证...
  • 此博客为个人博客,不涉及商业用途,仅提供学习参考,内容均来自个人原创以及互联网转载和摘录。 此博客上带原创标识...为什么MIPS处理器的数据通路中需要符号扩展单元和左移2位? 符号扩展单元 考虑MIPS的存取指令,
  • java中左移、右移、无符号右移

    千次阅读 2013-11-11 11:20:39
    计算机对有符号数(包括浮点数)的表示有三种方法:原码、反码和补码,补码=反码+1。在 二进制里,是用 0 和 1 来表示正负的,最高位为符号位,最高位为 1 代表负数,最高位为0 代表正数。  以java中8位的byte为例...
  • 如果是正数,无符号右移与有符号右移一样 比如:10>>>2,结果:2 我们重点说一下负数,区别在于,无符号右移, 高位补0 ,有符号右移,高位补1。 比如:-10>>>2,结果:1073741821 10的二进制为:11111111 ...
  • 有符号数与无符号数的移位运算

    千次阅读 2019-03-22 10:29:17
    有符号左移:逻辑左移,空位补0 右移:算数右移。若为正数,空位补0,若为负数,空位补1 无符号数 左移和右移均是逻辑位移,空位补0

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,339
精华内容 535
关键字:

有符号左移