`
春花秋月何时了
  • 浏览: 41820 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

关于Java按位取反“~”操作

 
阅读更多

前言

在分析一些jdk8的源码比如StampedLock的时候,发现有对long类型的变量进行“~”操作:

private static final long RBITS = 127;
private static final long SBITS = ~RBITS;

 上面的代码中,long型变量RBITS为127,通过对其进行“~”操作得到SBITS,通过Java编译器可以直接看到SBITS的值是-128,开始的时候我始终不明白这是怎样的一个演算过程,今天详细的记录在此。

 

按位取反

在说“~”操作即“按位取反”之前,需要注意它和平常所说的另一个概念“取反码”或者“反码”是不一样的,在Java中有原码反码补码之说,关于这三者有如下的转换规则:

(1)正数的原码,反码,补码完全一样,即符号位固定为0,数值位相同;

(2)负数的原码:最高位符号位为1,数值位表示其绝对值(其实就是和对应的正数相同),

         负数的反码:原码符号位1固定不变,数值位的每一位二进制按位取反得到反码,

         负数的补码:反码符号位1固定不变,在反码数值位最低位加1。

 

根据(2)负数的原码求补码的过程:补码=原码取反+1,我们可以逆运算得出,根据负数的补码求原码的方式为:负数原码=补码-1,再取反。

 

 因此,对一个数进行“~”操作即“按位取反”,得到的肯定不是它的“反码”,因为正数的反码固定不变,负数的反码虽说的确是进行了按位取反,但是它会保持符号位1固定不变,按位取反连符号位都会进行取反。

 

另外,关于补码存在的意义:补码其实是二进制数在内存中存在的形式,即不论是正数还是负数在内存中都是以其补码的形式存放的,而不是源码

 

接着说“~”操作即“按位取反”, 按位取反操作其实是对补码的操作,而非源码,所以在进行“~”操作之前需要先得到相应的补码。

 

示例

有了以上对“~”按位取反操作的相关的知识,现在再来进行对一个数进行按位取反操作就很明了了。

示例一、对最开始的long型变量127进行按位取反:

第一步:先得到补码。正数127的补码即为原码:0000000000000000 0000000000000000 0000000000000000 0000000001111111 

第二步:补码按位取反:1111111111111111 1111111111111111 1111111111111111 1111111110000000,这其实是对127按位取反之后在内存中的补码存放形式

为了知道这个按位取反的结果对应的十进制,我们需要通过补码求原码的公式,倒推得到原码之后才能知道对应的十进制是多少:

第三步:补码减1:

 

 1111111111111111 1111111111111111 1111111111111111 1111111110000000
-0000000000000000 0000000000000000 0000000000000000 0000000000000001
--------------------------------------------------------------------
 1111111111111111 1111111111111111 1111111111111111 1111111101111111
    结果为1111111111111111 1111111111111111 1111111111111111 1111111101111111

 

第四步:再根据补码减1的结果求反码得到对应的原码:  1000000000000000 0000000000000000 0000000000000000 0000000010000000,这就是-128的二进制原码

 

示例二、如果我们再对-128进行“~”操作结果会是多少?

第一步:“~”操作之前需要先得到-128的补码,负数的补码又需要先获得反码:

              -128原码为:1000000000000000 0000000000000000 0000000000000000 0000000010000000

              -128的反码:1111111111111111 1111111111111111 1111111111111111 1111111101111111

              反码数值位+1得补码:1111111111111111 1111111111111111 1111111111111111 1111111110000000

第二步:对-128的补码进行“~”按位取反操作结果为:

               0000000000000000 0000000000000000 0000000000000000 0000000001111111,这就是对-128按位取反之后在内存中的补码存放形式

第三步:为了知道对应的十进制,需要由补码转换为原码,由于结果是一个正数(最高位符号位为0),其原码和补码相同还是:

               0000000000000000 0000000000000000 0000000000000000 0000000001111111,所以这就是对-128进行按位取反之后的原码,十进制为127.

 

故而:-128进行“~”操作结果127

 

分享到:
评论

相关推荐

    javascript中的取反再取反~~没有意义

    操作符~, 是按位取反的意思,表面上~~(取反再取反)没有意义,实际上在JS中可以将浮点数变成整数。 代码如下: <html> [removed] var myArray = new Array(); myArray.push(“a”); myArray.push(“b”); ...

    java 按位操作符的使用

    在Java中,按位操作符用于对整数进行位级别的操作 按位与(&)操作符 按位或(|)操作符 按位异或(^)操作符 按位取反(~)操作符 左移()操作符 右移(>>)操作符

    java位运算大全.doc

    位运算符可以结合这些整型变量进行各种位级操作,例如通过按位与(&)来设置或清除特定位,按位或(|)来设置位,按位异或(^)来进行位级别的XOR操作,按位右移(>>>或>>)来移动位,左移()将位向左移动,以及按位取反(~)来...

    java 位操作集合以及应用技巧

    4. 按位非(~):对操作数的每一位取反,0变1,1变0。 5. 左移():将操作数的二进制位向左移动指定的位数,右边补0。 6. 右移(>>):将操作数的二进制位向右移动指定的位数,左边高位根据符号位决定补0还是补1(有符号...

    java位运算,符号运算 详细解释

    4. 按位非(~):对操作数的每一位取反,0变为1,1变为0。 5. 左移():将操作数的二进制位向左移动指定的位数,右边用0填充。 6. 右移(>>):将操作数的二进制位向右移动指定的位数,左边的高位丢弃,对于有符号整数,...

    java位运算大全.pdf

    值得注意的是,除按位取反(~)外,其余的都是二元运算符,即它们需要两个操作数。这些运算符只能作用于整型和字符型数据。 基础的位运算知识中,Java的整数类型(char除外)都是有符号的,即可以表示正数和负数。...

    JAVA位运算.pdf

    - **按位非(NOT)**:`~`,这是一个一元运算符,对操作数的每一位进行取反操作。例如,对于数字42(二进制形式为`00101010`),应用按位非运算后变为`11010101`。 - **按位与(AND)**:`&`,如果两个操作数的...

    Java中的位运算

    - **按位取反(~)**:将每个位取反,即0变1,1变0。 - **左移位()**:将操作数的所有位向左移动指定的位数,高位丢弃,低位补0。 - **右移位(>>)**:将操作数的所有位向右移动指定的位数,对于正数,高位补0;...

    位运算课件(java学习位运算课件)

    位运算在Java编程中是底层操作,用于直接处理二进制数据,对于理解计算机内部机制和优化代码性能至关重要。本文将深入探讨位运算的相关知识,包括计算机中数据的表示方法、二进制计数系统、以及原码、反码和补码的...

    20191220-Java位运算_java_位运算_

    Java位运算在编程中是一种非常基础且强大的操作,它直接作用于二进制位,能够进行高效的数值处理和数据操作。本文将深入讲解Java中的位运算,并通过雪花算法的应用实例来进一步阐述其重要性和用法。 1. **位运算...

    Java 中的位运算

    - **按位非 (`~`)**:对二进制数进行按位取反操作,即将每个位上的值反转。 - 示例:`~5 = -6` - `5` 的二进制表示为 `00000000000000000000000000000101`,按位非操作后得到 `11111111111111111111111111111010`...

    Java基础入门学习教程PPT课件 JAVA语言程序设计 JAVA_03 JAVA语言基础 位运算(共21页).ppt

    按位非"~"运算符对一个数的所有位进行取反操作。左移"是将数字的二进制位向左移动指定的位数,相当于乘以2的幂次;右移">>"则是向右移动,相当于除以2的幂次。 在Java编程中,理解位运算和它们的应用场景对于编写...

    C#中的位操作小结

    位操作是其他很多语言都支持的操作,如C、C++和Java等,C#也不例外支持位操作。注意位操作支持的数据类型是基本数据类型,如byte、short、char、int、long等,C#支持的位操作有如下几种: •按位与 &•按位或 |•按位...

    java位运算

    Java位运算是一种在计算机科学中广泛使用的操作,它涉及到对二进制位的直接操作,包括按位与、按位或、按位异或、按位非、左移、右移以及无符号右移等。这些操作对于理解底层计算原理、优化代码性能以及在特定场景下...

    CoreJava全套详细笔记资料.pdf

    * 位运算符包括按位与、按位或、按位异或和按位非,用于对数字进行二进制操作。 * 逻辑运算符包括逻辑与、逻辑或和逻辑非,用于对布尔值进行逻辑操作。 四、流程控制 * 流程控制是Java语言中的控制结构,用于控制...

Global site tag (gtag.js) - Google Analytics