前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >按位取反的概念和计算方法「建议收藏」

按位取反的概念和计算方法「建议收藏」

作者头像
全栈程序员站长
发布2022-09-21 11:04:57
4K0
发布2022-09-21 11:04:57
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君

读本文前请首先搞懂 “反码”,“取反”,“按位取反(~)”,这3个概念是不一样的。

取反:0变1,1变0

反码:正数的反码是其本身,对于负数其符号位不变其它各位取反(0变1,1变0)

按位取反(~): 这将是下面要讨论的。

“~”运算符在c、c++、java、c#中都有,之前一直没有遇到这个运算符。

要弄懂这个运算符的计算方法,首先必须明白二进制数在内存中的存放形式,二进制数在内存中是以补码的形式存放的。

另外正数和负数的补码不一样,正数的补码、反码都是其本身,既:

正数9:

原码为: 0000 1001

补码为: 0000 1001

反码为: 0000 1001

再例如: -2

求原码: 1111 0010 (前面4个1表示符号位)

求反码: 1111 1101 (符号位不变,其余各位求反)

求补码: 1111 1110 (符号位不变,末位+1)

所以-2在内存中存放为: 1111 1110

————————————————————————————————-

弄懂了上述情况后,如何计算就好办了

假设要对正数9按位取反——> (~9),计算步骤如下,

原码为 0000 1001,

反码为 0000 1001,

补码为 0000 1001,

对其取反 1111 0110(符号位一起进行取反,这不是反码更加不是最终结果,只是补码的取反仅此而已)

我们还需要把他转换成原码,因为是负数所以进行负数补码到原码的逆运算

先减1得反码: 1111 0101

取反得原码:1111 1010,(反码和原码是一个相对的概念,对反码取反就是原码。取反过程符号位是不变的哦)

前面4个1是符号位,1是负数,既得十进制:-10

不知道说的明不明白,这里步骤就是:

1. 先对正数求补码

2. 然后对补码取反,包括符号位

3. 最后进行一个补码求原码的过程,一定要搞清概念啊。

————————————————————————————————-

下面我们再反推计算 (~ -10)

-10的原码:1111 1010

-10的反码:1111 0101 (符号位不变)

-10的补码:1111 0110 (符号位不变,末位+1)

补码取反:0000 1001 (符号位一起取反)

这是一个正数,那么我们对其求原码就可得到最终结果?

因为正数的补码,反码,原码都是一样的 那我们的最终结果是 0000 1001 ,十进制是 9,这与我们前面推算出的结果吻合。

————————————————————————————————-

最后一个有趣的事实是:

1. 所有正整数的按位取反是其本身+1的负数

2. 所有负整数的按位取反是其本身+1的绝对值

3. 零的按位取反是 -1(0在数学界既不是正数也不是负数)

[cpp] view plain copy

  1. // 测试-1亿 到 1亿的所有整数 :)
  2. for (int i = 0; i <= 100000000;++i)
  3. {
  4. if (~i != -(i+1) )
  5. {
  6. __asm { cli } // 汇编中断指令
  7. }
  8. if (i && ~(-i) != abs((-i)+1) )
  9. {
  10. __asm { cli }
  11. }
  12. }

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/170469.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档