常用位运算

为了避免日后忘记,故简单记录基本的位运算。


二进制:

二进制数在内存中是以补码的形式存放的。(所以取反是按照补码来运算的,注意反码和取反不是同一个操作,取反时符号位也会变化)


原码、反码、补码,补码是为了解决正数原码+负数原码和不为0的情况(0000 0001 + 1000 0001不等于0),所以我们认定正数的表示形式没问题,所以正数的补码(计算用的)即为原码。
1. 正数(以十进制的5为例)
原码:即普通的8421码0101,第一位为符号位。
反码:正数的反码等于自身,即原码:0101
补码:正数的补码等于自身,即原码:0101


2. 负数(以十进制的-5为例)
原码:即普通的8421码1101,第一位为符号位。
反码:符号位不变,其余各位求反,即:1010

补码:符号位不变,其余各位求反,末位加1,即:1011


注意:有符号数相加,忽略进位标志。
e.g. 5 + (-4)
                            0 1 0 1
                         + 1 1 0 0  (注意,-4的原码和补码是一样的,计算使用的补码)
                     ----------------
                         1  0 0 0 1  (同理,结果也是补码,这里正数的补码就是原码)

    忽略进位得0001,即为1。

为避免误会,再举例 -5 + 4:
                            1 0 1 1 (补码,-5的原码为1101,反码为1010,补码为1011)
                         + 0 1 0 0 (补码,正数的原码、反码、补码都是同一个)
                     ---------------- 
                            1 1 1 1 (补码,原码为1001,即-1)

    没有进位,1111为补码,换算之后(或者直接看出来)其原码为1001,即为-1。

原码、反码、补码,补码是为了解决正数原码+负数原码和不为0的情况(0000 0001 + 1000 0001不等于0),所以我们认定正数的表示形式没问题,所以正数的补码(计算用的)即为原码。
1. 正数(以十进制的5为例)
原码:即普通的8421码0101,第一位为符号位。
反码:正数的反码等于自身,即原码:0101
补码:正数的补码等于自身,即原码:0101


2. 负数(以十进制的-5为例)
原码:即普通的8421码1101,第一位为符号位。
反码:符号位不变,其余各位求反,即:1010
补码:符号位不变,其余各位求反,末位加1,即:1011

异或的几条性质:

1、交换律
2、结合律(即(a^b)^c == a^(b^c))
3、对于任何数x,都有x^x=0,x^0=x

4、自反性:  a^b^b=a^0=a;

与的特征:
a&b,结果肯定小于等于min(a,b)


3. 下面是一个毫无卵用的例子,虽然没用,但是要知道这是什么,这又是为什么?
-~n (结果等效为 n+1,下面是分析)
以n=5为例子:
n的补码为:0101
n取反(~n)为:1010,(此时1010为补码,故1010->1001-->1110=-6)
再取负号(-~n)为:-(-6) 即为6


以n=-5为例子:
n的补码为:1011
n取反为:0100,(正数的补码即原码,故0100=4)
再取负号:-4 即为 -4


附上例子代码:
        // 以下注释皆为补码,位运算时,内存中保存的二进制位补码。
        // 有符号数-(1010),注意-是取相反数,不能直接修改1010的符号位,应该换成原码之后再取反,或者直接算出结果。
        System.out.println(-~5); // ~0101 = 1010,(1010->1001-->1110=-6),故-1010(补码)=-1110(原码)=-(-6)=6
        System.out.println(-~(-5)); // ~1011 = 0100,故-0100(补码即原码)=-4
        // 位数不够的参数左边补符号位
        System.out.println(3 & 4); // 0011(011) & 0100 = 0000=0
        System.out.println(3 ^ 4); // 0011(011) ^ 0100 = 0111=7
        System.out.println(3 & -4); // 0011(011) & 1100 = 0000=0
        System.out.println(-3 & -4); // 1101(101) & 1100 = 1100,(1100-->1011-->1100=-4)
        System.out.println(~2); // ~010 = 101,(101-->100-->111=-3)


瞎写的,可能看起来不那么顺畅,凑合着看吧
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值