`
春花秋月何时了
  • 浏览: 39747 次
  • 性别: 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中,按位操作符用于对整数进行位级别的操作 按位与(&)操作符 按位或(|)操作符 按位异或(^)操作符 按位取反(~)操作符 左移()操作符 右移(>>)操作符

    C#中的位操作小结

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

    JAVA基础之java的移位运算

    按位非也叫做补,一元运算符NOT“~”是对其运算数的每一位取反。例如,数字42,它的二进制代码为: 00101010 经过按位非运算成为 11010101 按位与(AND) 按位与运算符“&”,如果两个运算数都是1,则结果为1...

    2.Java基础语法.ppt

    只要第一个操作数是false,那么结果一定是false,那么后面的那个操作数就不用计算了。提高了 效率。 逻辑或 | 只要有一个是true,那么结果就是true 短路或 || 短路或与逻辑或 结果一模一样。只要第一个操作数是true...

    js实现特定位取反原理及示例

    机试题碰到了这道位运算的题目,按理说是非常简单的,原理笔者也很清楚,但是由于实在是好多年没有搞过位运算了,Java位运算更是没有操作过,所以结果实在是不体面…… 机试时间规定是一个小时,语言可选C或Java还有...

    java课程设计-计算器-功能完整的科学计算器-仿windows计算器

    java课程设计,里面包含源程序和课程设计报告 题目要求:编写一计算器,仿照windows xp计算器界面,能实现基本的运算及一些科学运算。 能实现的运算如下: "+",加 "-",减 "*",乘 "/",除 "x^y",x的y次方 "Mod",取模 ...

    java基础,笔记03

    3 取反加一 111111 32位全是1 11111110000000 一共32位 负的二进制数 >负的十进制数 1 减1取反 或取反加1 0000001 00000010000000 2 转换为十进制正数 1 128 3 乘 1 1 128...

    hive函数大全(中文版)

    9.位取反操作: ~ 10 三、逻辑运算: 10 1. 逻辑与操作: AND 10 2. 逻辑或操作: OR 10 3. 逻辑非操作: NOT 10 四、数值计算 11 1. 取整函数: round 11 2. 指定精度取整函数: round 11 3. 向下取整函数: floor 11 4. ...

    微软JavaScript手册

    按位取非运算符 对一个表达式执行按位取非(求非)操作。 按位或运算符 (|) 对两个表达式指定按位或操作。 按位右移运算符 (>>) 将一个表达式的各位向右移,保持符号不变。 按位异或运算符(^) 对两个表达式...

    了解Java中的运算符

    1. 运算符 1.1 关系运算符 ...1. 自增自减运算符有且只能操作变量!!! 2. 自增自减运算符独立存在!!!单独成行,减少代码中的歧义!!! 3. 【个人建议】 使用 += 1 和 -= 1 替代自增自减运算符 S

    javascript运算符——逻辑运算符全面解析

    前面的话 逻辑运算符对操作数进行布尔运算,经常...逻辑非对操作数转为布尔类型的转换类型与Boolean()转型函数相同,只不过最后再将其结果取反。而如果同时使用两个逻辑非操作符,实际上就会模拟Boolean()转型函数的行

    数据分析—排序.pdf

    数据分析—排序 排序是数据分析中最常⽤的操作,没有之⼀。 单字段升序: 利⽤ mapreduce ⾃⾝的排序机制,把需要排序的字段作为 key 即可 其它排序: ⾃定义排序规则 ⽅案⼀:⾃定义 key 1. ⾃定义类实现 ...

    【03-流程控制与数组】

    •只要类型相互兼容,可以让一个数组变量指向另一个实际的数组,这种操作会产生数组的长度可变的错觉。 •但由于数组变量整体赋值导致的数组的长度可以改变,只是一个假相。 基本类型数组的初始化 •对于...

    Oracle练习笔试大全

    //(可以对in指定的条件进行取反) 22、select ename from emp where ename like '%ALL%'; //(模糊查询) 23、select ename from emp where ename like '_A%'; //(取第二个字母是A的所有字段) 24、select ename ...

    Python编程入门经典

    4.4 对真值和假值取反 53 4.5 观察多个比较运算的结果 54 4.6 循环 57 4.6.1 重复执行操作 57 4.6.2 终止循环 59 4.7 处理错误 62 4.8 本章小结 64 4.9 习题 65 第5章 函数 67 5.1 将程序放在单独的文件中 67 5.2 ...

    精通JavaScript

    • 2.14.htm 使用值的数据操作 • 2.15.htm 对数据的引用执行 • 2.16.htm 字符串的比较 第3章(\第3章) • 3.1.htm 表达式示例 • 3.2.htm 加号运算符应用 • 3.3....

    精通javascript

    • 2.14.htm 使用值的数据操作 • 2.15.htm 对数据的引用执行 • 2.16.htm 字符串的比较 第3章(\第3章) • 3.1.htm 表达式示例 • 3.2.htm 加号运算符应用 • 3.3....

    精髓Oralcle讲课笔记

    --(可以对in指定的条件进行取反) 22、select ename from emp where ename like '%ALL%'; --(模糊查询) 23、select ename from emp where ename like '_A%'; --(取第二个字母是A的所有字段) 24、select ename ...

Global site tag (gtag.js) - Google Analytics