Bit operation Kotlin/Java 位运算

# Java Kotlin 口诀
按位与 & and() 1&1 得 1,其他全 0
按位或 ` ` or()
按位非 ~ inv() 0 变 1 啊,1 变 0
按位异或 ^ xor() 相同为 0 不同为 1
左移运算符 << shl() 左移乘 2
右移运算符 >> shr() 右移除 2
无符号右移运算符 >>> ushr()

Kotlin source code

    /** Shifts this value left by the [bitCount] number of bits. */
    public infix fun shl(bitCount: Int): Int
    /** Shifts this value right by the [bitCount] number of bits, filling the leftmost bits with copies of the sign bit. */
    public infix fun shr(bitCount: Int): Int
    /** Shifts this value right by the [bitCount] number of bits, filling the leftmost bits with zeros. */
    public infix fun ushr(bitCount: Int): Int
    /** Performs a bitwise AND operation between the two values. */
    public infix fun and(other: Int): Int
    /** Performs a bitwise OR operation between the two values. */
    public infix fun or(other: Int): Int
    /** Performs a bitwise XOR operation between the two values. */
    public infix fun xor(other: Int): Int
    /** Inverts the bits in this value. */
    public fun inv(): Int

LeetCode 476 Number Complement

Given a positive integer, output its complement number. The complement strategy is to flip the bits of its binary representation.

  • 用一个具体的例子讲一下这题的思路。比如说十进制的 5,用二进制表示是 0(28 个) + 0101
    有效的二进制是 101 取其补码是 010,有效二进制 0(30 个) + 10 表示十进制二
  • 第一步计算出二进制的 5 前边有几个 0,用 Integer 类的numberOfLeadingZeros方法,结果是 29 个
  • 第二步把二进制的按位做非运算得到 1(29 个) + 010
  • 第三步把它左移 29 位得到 010 + 0(29 个)
  • 第四部把它再右移 29 位得到 0(29 个) + 010 也是就十进制的 2
/*
0000 ... 0101 ==> 5 (leadingZero = 32-3 = 29) inv
1111 ... 1010
*/
fun findComplement(num: Int): Int {
    val leadingZero = Integer.numberOfLeadingZeros(num)
    return num.inv().shl(leadingZero).shr(leadingZero)
}
/*
0000 ... 0101 ==> 5
1111 ... 1111 ==> Int.MAX_VALUE

1111 ... 1000 and
0000 ... 0101
0000 ... 0000 ==> 0

1111 ... 1000 inv
0000 ... 0111

0000 ... 0101 inv
1111 ... 1010

0000 ... 0111 and
1111 ... 1010
==
0000 ... 0010 ==> 2
*/
fun findComplement(num: Int): Int {
    var flag = Int.MAX_VALUE
    while (flag.and(num) != 0) {
        flag = flag.shl(1)
    }
    return (flag.inv()).and(num.inv())
}