`

java位移运算符详解

 
阅读更多

转自:https://www.cnblogs.com/winsker/p/6728672.html

 

    移位运算符操作的对象就是二进制的位,可以单独用移位运算符来处理int型整数。

 运算符       含义       例子      
<< 左移运算符,将运算符左边的对象向左移动运算符右边指定的位数(在低位补0) x<<3
>> "有符号"右移运算 符,将运算符左边的对象向右移动运算符右边指定的位数。使用符号扩展机制,也就是说,如果值为正,则在高位补0,如果值为负,则在高位补1. x>>3
>>> "无符号"右移运算 符,将运算符左边的对象向右移动运算符右边指定的位数。采用0扩展机制,也就是说,无论值的正负,都在高位补0. x>>>3

  

 

以int类型的6297为例,代码如下:(注意:位移运算符结果必须赋值给一个对象或者作为参数传入方法如下,否则报错“not a statement”)

  1. System.out.println(Integer.toBinaryString(6297));   
  2. System.out.println(Integer.toBinaryString(-6297));   
  3. System.out.println(Integer.toBinaryString(6297>>5));   
  4. System.out.println(Integer.toBinaryString(-6297>>5));   
  5. System.out.println(Integer.toBinaryString(6297>>>5));   
  6. System.out.println(Integer.toBinaryString(-6297>>>5));   
  7. System.out.println(Integer.toBinaryString(6297<<5));   
  8. System.out.println(Integer.toBinaryString(-6297<<5));  

 

  运行结果:

1100010011001
11111111111111111110011101100111
11000100
11111111111111111111111100111011
11000100
111111111111111111100111011
110001001100100000
11111111111111001110110011100000

注:x<<y 相当于 x*2;x>>y相当于x/2y
    从计算速度上讲,移位运算要比算术运算快。
    如果x是负数,那么x>>>3没有什么算术意义,只有逻辑意义。

 

在Think in Java中有这么一段话

写道
“对char,byte或者short进行移位处理,那么在移位进行之前,它们会自动转换成一个int。只有右侧的5个低位才会有用。这样可防止我们在一个int数里移动不切实际的位数。若对一个long值进行处理,最后得到的结果也是long。此时只会用到右侧的6个低位,防止移动超过long值里现成的位数。”

 

 

这段话有两个出处,一个是Java编程思想3.11移位操作符中出现,原话是“只有数值右端的低5位才有用”。一个是Java解惑中谜题27:变幻莫测的i值,原话是“移位操作符只使用其右操作数的低5位作为移位长度”。

弄清这句话首先需要弄清楚移位操作符,移位操作符是一个二元操作符,两个操作数分别位于移位操作两边形如:左操作数 移位操作符 右操作数 这样的结构,其含义是,将左操作数按照移位操作符指定的移位方向,进行右操作数指定的次数的移位。然后对照出处二,Java解惑中所描述的,就豁然开朗了。

首先,移位操作符能操作的数只有int类型和long类型,这个是指左操作数的类型。对于int类型而言,int在Java中占4字节,一共32位,也就是说,对于一个在Java中的int数据,做32次移位,那么这个int数据就完全变了,以左移为例,左移是补0,那么对于任意一个int类型数据,做32次移位,那么int数据变成32位全0的数据,Java不允许一次性移位左操作数的所有位,也就是右操作数不能大于32。于是回到上述的句子,其指的是右操作数的低5位,5位二进制所代表的最大值为2^5-1,为31,所以取右操作数的低5位,就是只看右操作数的二进制的低5位,其数值不会超过2^5次方,也就是int的32位。因此,移位操作符进行移位的实际次数,其实是右操作数2的次数。


对上面那段话的理解是:移位操作符操作的运算对象是二进制的“位”,int类型是32位也就是2的5次幂 !如果移32位以上,那么原来的数的信息会全部丢失,这样也就没有什么意义了!所以上面的“只有右侧的5个低位才会有用”说的是:移位操作符右端的那个数(化成二进制)的低5位才有用,即
X < <y;

是指y的低5位才有用,即不能大于32。 而对于long型也是同样的道理!

因此,如果对一个int 型,进行移位,X < <y; 当y小于32时,移位后的结果一般都在我们的预料当中;而如果y大于32时,由于移位超出了int所能表示的范围,这时就先把y化成二进制数,然后取该二进制数右端的低5位,再把这5位化成十进制,此时的这个十进制就是要对X移动的位数。
例如:

int int a=140;
a << 34
System.out.println(Integer.toBinaryString(a << b));

上面那两个语句的执行过程是:先把a化成二进制数:10001100

执行语句 a << 34 对a左移32位时,先把 34化成二进制:100010,对该二进制数取右边5位,即00010,化成十进制数为2,所以实际上是对a左移两位。现在,地球人都会知道上面程序的输出结果是:1000110000

//////////////////////////////////////////////////
移位运算符和按位运算符一样,同属于位运算符,因此移位运算符的位指的也是二进制位。它包括以下几种:
左移位(<<):将操作符左侧的操作数向左移动操作符右侧指定的位数 。移动的规则是在二进制的低位补0。

有符号右移位(>>):将操作符左侧的操作数向右移动操作符右侧指定的位数。移动的规则是,如果被操作数的符号为正,则在二进制的高位补0;如果被操作数的符号为负,则在二进制的高位补1。

无符号右移位(>>>):将操作符左侧的操作数向右移动操作符右侧指定的位数。移动的规则是,无论被操作数的符号是正是负,都在二进制位的高位补0。
注意,移位运算符不存在“无符号左移位(<<<)”一说。与按位运算符一样,移位运算符可以用于byte、short、int、long等整数类型,和字符串类型char,但是不能用于浮点数类型float、double;当然,在Java5.0及以上版本中,移位运算符还可用于byte、short、int、long、char对应的包装器类。我们可以参照按位运算符的示例写一个测试程序来验证,这里就不再举例了。
与按位运算符不同的是,移位运算符不存在短路不短路的问题。
写到这里就不得不提及一个在面试题中经常被考到的题目:

写道
请用最有效率的方法计算出2乘以8等于几?这里所谓的最有效率,实际上就是通过最少、最简单的运算得出想要的结果,而移位是计算机中相当基础的运算了,用它来实现准没错了。左移位“<<”把被操作数每向左移动一位,效果等同于将被操作数乘以2,而2*8=(2*2*2*2),就是把2向左移位3次。因此最有效率的计算2乘以8的方法就是“2<<3”。

 

最后,我们再来考虑一种情况,当要移位的位数大于被操作数对应数据类型所能表示的最大位数时,结果会是怎样呢?比如,1<<35=?呢?
这里就涉及到移位运算的另外一些规则:
byte、short、char在做移位运算之前,会被自动转换为int类型,然后再进行运算。 byte、short、int、char类型的数据经过移位运算后结果都为int型。 long经过移位运算后结果为long型。

在左移位(<<)运算时,如果要移位的位数大于被操作数对应数据类型所能表示的最大位数,那么先将要求移位数对该类型所能表示的最大位数求余后,再将被操作数移位所得余数对应的数值,效果不变。

比如1<<35=1<&lt;(352)=1<<3=8。 对于有符号右移位(>>)运算和无符号右移位(>>>)运算,当要移位的位数大于被操作数对应数据类型所能表示的最大位数时,那么先将要求移位数对该类型所能表示的最大位数求余后,再将被操作数移位所得余数对应的数值,效果不变。。

比如100>>35=100>>(352)=100>>3=12。

另:

Java 的 Integer.toBinaryString 方法

public static String toBinaryString(int i)

    //以二进制(基数 2)无符号整数形式返回一个整数参数的字符串表示形式。 
    //如果参数为负,该无符号整数值为参数加上 2^32;否则等于该参数。

        System.out.println(Integer.toBinaryString(-1)) ;
        System.out.println(Integer.toBinaryString(-2)) ;
        System.out.println(Integer.toBinaryString(1)) ;
    输出:
        11111111111111111111111111111111
        11111111111111111111111111111110
        1

结论输出的是数字的二进制补码。为什么说是以 二进制无符号整数形式 返回一个 整数类型的字符串,为什么 如果参数为负数,就要加上 2的32 次方?

因为Java里的int是有符号的,在内存中没有正负之分,只有0/1,整数是用补码表示的

正数补码等于原码
负数的补码等于其绝对值的反码+1,正好等于自身+2^32(对于4字节的整型来说)

-1 的补码 就是 绝对值1 的反码(按位取反) 11111111 11111111 11111111 11111110 再+1
等于 11111111 11111111 11111111 11111111

这样正好能把最高位为1的数字用来表示负数,而最高位为0的数字表示非负数

10000000 00000000 00000000 00000000 => -2147483648
11111111 11111111 11111111 11111111 => -1
00000000 00000000 00000000 00000000 => 0
00000000 00000000 00000000 00000001 => 1
01111111 11111111 11111111 11111111 => 2147483647

因此负数+2^32之后的二进制串,就是该负数内存中准确的存储形式

分享到:
评论

相关推荐

    Java移位运算符详解实例(小结)

    Java移位运算符详解实例 Java移位运算符是Java语言中的一种基本运算符,用于对二进制数进行位移操作。移位运算符主要包括左移位运算符()、右移位运算符(&gt;&gt;&gt;)和带符号的右移位运算符(&gt;&gt;)。这些运算符可以单独...

    Java运算符优先级别.doc

    5. **位移运算符** `, `&gt;&gt;`, `&gt;&gt;&gt;`:从左到右结合。 - **左移** `将二进制数的各位向左移动。 - **右移** `&gt;&gt;`:将二进制数的各位向右移动。 - **无符号右移** `&gt;&gt;&gt;`:与右移类似,但高位补0。 6. **比较运算符*...

    Java程序设计基础:运算符与表达式.pptx

    #### 四、具体运算符详解 - **算术运算符**: - `+`:加法运算。 - `-`:减法运算。 - `*`:乘法运算。 - `/`:除法运算。 - `%`:取模运算,返回除法的余数。 - **自增自减运算符**: - `++`:自增运算符,...

    最新最全2012年Java面试宝典

    最有效率的方法是使用位移运算符`,即`2 ,相当于2乘以2的3次方,结果是16。 **1.9 设计一个一百亿的计算器** 对于处理非常大的数字,可以使用`BigInteger`类,它是Java提供的一个用来处理大整数的类。 **1.10 ...

    JAVA位运算.pdf

    ### JAVA位运算详解 在Java编程中,位运算是一门精细的艺术,涉及到对整数类型的二进制位进行直接操作。这些操作不仅能够优化代码执行效率,还常用于实现特定的算法需求。本文将深入探讨Java中的位运算,包括位...

    java面试题大全好多经典的试题

    位移运算符示例:2 的结果是什么?** `2 表示将2的二进制表示左移3位,即0010变为100000,因此结果为32。 **15. String类有length()方法吗?** 是的,`String`类确实有`length()`方法,用于返回字符串的长度。 ...

    JAVA开发基于Misty1算法的加密软件(JAVA)的实现(源代码+论文).zip

    在Java中,可以使用位移运算符`&gt;&gt;&gt;`和`来实现行移位,使用异或操作符`^`来实现列混淆。 5. **轮密钥加** 轮密钥加是将密钥与当前轮的中间结果进行异或,增加算法的不可预测性。在Java中,这可以通过简单的异或操作...

    java考试重点(1001093449).pdf

    - **位移运算符**: - `&gt;&gt;` 和 `&gt;&gt;&gt;`: 分别代表算术右移和逻辑右移。 #### 四、总结 本篇文章通过对给定文件标题、描述、标签以及部分内容的分析,深入探讨了Java考试中涉及的重要知识点。从Java开发工具、语言...

    Java语言的26个细.doc

    在Java中,位移运算符(`和 `&gt;&gt;`)用于将二进制位向左或向右移动指定的位置。然而,Java对位移运算进行了一项优化处理,特别是当移位的数量超过32位时。根据Java规范,对于`int`类型,如果位移量超过32位,实际上...

    Java编程基础语法

    ### Java编程基础语法详解 #### 一、Java语言概述与特点 Java作为一种广泛使用的编程语言,其设计初衷是为了实现“一次编写,到处运行”的理念。Java语言由语法规则和类库两大部分组成,其中语法规则是编程的基础...

    Java笔试题(完整最新版)

    - **知识点概述**:可以使用位移运算符`来快速计算2乘以8,即`2 。 #### 六、static方法内部调用非static方法的可能性 - **知识点概述**:从静态(`static`)方法内部无法直接调用非静态方法。非静态方法依赖于...

    java面试题-含答案.pdf

    - 用最有效率的方法计算 `2 * 8` 可以直接写 `2 ,这是利用位移运算符进行快速乘法。 以上是对 Java 面试题中涉及的基础知识的详细解释,涵盖了面向对象、数据类型、操作符、内存管理和控制流等多个方面。理解并...

    Java最新面试宝典

    ### Java最新面试宝典知识点详解 ...- 使用位移运算符 `是计算 2 的倍数的一种非常高效的方法。 ```java int result = 2 ; // 结果为 4 ``` - 位移运算比乘法运算更快,特别是在处理大整数时效率更高。

    Java面试宝典2010版

    8. **效率计算2乘以8**:最有效率的方法是使用位移运算符:`2 ,这相当于2乘以2的3次方,即8。 9. **设计大整数计算器**:设计一个能处理大整数的计算器,可以使用BigInteger类,它能处理超过int和long范围的大整数...

    java ssh面试宝典

    计算`2*8`的最有效率方式可能是使用位移运算符:`2 ,这相当于将二进制数左移三位,达到乘以8的效果。 **9. 设计一个百亿级计算器** 设计百亿级计算器涉及到大数运算,可以使用Java的`BigInteger`类,它提供了处理...

    Java面试宝典2011最新版

    ### Java面试宝典2011最新版知识点详解 #### 1. Java基本概念与面试常见问题 **1.1 “.java”源文件是否必须包含一个public类?** 解答:一个`.java`源文件不一定要包含一个`public`类。但是,如果包含了`public`...

    java面试宝典

    ### Java面试宝典知识点详解 #### 一、Java基础部分 **1. 一个“.java”源文件中是否可以包括多个类(不是内部类)?有什么限制?** 在一个`.java`源文件中可以定义多个类,但有一个重要的限制:每个源文件只能有...

    二进制的基础上的位运算

    本文将详细介绍五种基本的位运算符:按位与(`&`)、按位或(`|`)、按位异或(`^`)、按位取反(`~`)以及位移运算符(`, `&gt;&gt;`, `&gt;&gt;&gt;`)。 #### 二、按位与(`&`) 按位与运算符用于两个二进制数对应位上的逻辑...

Global site tag (gtag.js) - Google Analytics