「位运算学习」C++卡常之i++ -> i=-~i

其实本篇文章不是为了卡常,而是为了讲解位运算的一个应用(

前置芝士

原码表示法是整数的一种简单的表示法,符号位用 \(0\) 表示正号,用 \(1\) 表示负号,数值一般用二进制形式表示。


整数的反码和补码

正数 负数 \(+0\)「看作正数」 \(-0\)「看作负数」
原码 符号位为 \(0\)
数值位用二进制表示
符号位为 \(1\)
数值位用二进制表示
\(00000000\) \(10000000\)
反码 与原码相同 符号位为 \(1\)
数值位在原码基础上按位取反
\(00000000\) \(11111111\)
补码 与原码相同 在反码基础上 \(+1\) \(00000000\) \(00000000\)

(关于补码的详细知识,可以参考知乎上的一篇回答

简单来记:负数的补码形式可以由对应正数的二进制按位取反后 \(+1\) 得到,且负数符号位为 \(1\)


取反

~:取反(把运算数的各个二进制按位求反)

\(e.g.\)

  1. ~\(9\)

    原码:\(00001001\)

    「这里最左位的 \(0\) 表示正,如果是 \(1\) 就表示负,其余位按二进制表示」

    反码:\(00001001\)

    「正数的反码等于它的原码」

    补码:\(00001001\)

    「正数的补码等于它的原码」

    按位取反:\(11110110\)

    「这时得到的是取反后的补码,我们要把它转化成原码」

    「因为第一位是 \(1\),所以这是负数,要按照负数的转换法则倒退回去」

    \(负数的反码+1=补码\),因此\(负数的反码=补码-1\)

    反码:\(11110101\)

    「负数的原码按位取反(符号位除外)即为反码,因此负数的反码按位取反(符号位除外)就可转换为原码」

    原码:\(10001010\)

    转换为十进制,即为:\(-10\)

  2. ~\(-9\)

    原码:\(10001001\)

    「最左位是 \(1\) 表示是负数」

    反码:\(11110110\)

    「负数的原码转换为反码,符号位不变,其余位按位取反」

    补码:\(11110111\)

    「负数的反码转换为补码,\(+1\) 即可」

    按位取反:\(00001000\)

    「按位取反后为正数,因为正数的补码等于原码,所以直接转十进制即可」

    转十进制,即为:\(8\)


这时可以进入正题了。




C++ 循环的一个奇技淫巧

for(int i=1;i<=n;i++)

这应该算写的最多的代码之一了,殊不知它还可以写成这样:

for(int i=1;i<=n;i=-~i)

i=-~i 等价于 i++,但据说要比 i++ 快一些。大概类似于 ++ii++ 快一些吧。「其实也快不了多少,毕竟有编译器优化……

update:

见善则迁,有过则改。

——《周易》

此处对上面的说法绳愆纠缪。具体详见【Debug心得&笔记——⑳ i++++i 的那些事儿】。




正确性证明

\(x\)在二进制下表示为:\(abcdefgh\)

\(a\)取反后为\(A\)


  • \(x>=0\)时,\(a=0\)

    原码:\(0bcdefgh\)

    反码:\(0bcdefgh\)

    补码:\(0bcdefgh\)

    取反:\(1BCDEFGH\)

    反码:\(1BCDEFGH\color{red}-1\)

    「这里\(\color{red}-1\)就是将从右往左数第一个为\(1\)的数变为\(0\),它右边所有的\(0\)变为\(1\)

    「所以在变为原码时,从右往左数第一个为\(0\)的数变为\(1\),它右边所有的\(1\)变为\(0\),其余位按位取反」

    原码:\(1bcdefgh\color{red}+1\)

    这时转为十进制即为:\(-x-1\)

    再取相反数即为:\(x+1\)

  • \(x<0\)时,\(a=1\)

    原码:\(1bcdefgh\)

    反码:\(1BCDEFGH\)

    补码:\(1bcdefgh\color{red}-1\)

    取反:\(0BCDEFGH\color{red}+1\)

    反码:\(0BCDEFGH\color{red}+1\)

    这时转为十进制即为:\(-x-1\)

    再取相反数即为:\(x+1\)


证毕。

posted @ 2021-08-18 20:30  凌云_void  阅读(740)  评论(3编辑  收藏  举报