Kotlin位运算

发布于:2025-07-28 ⋅ 阅读:(13) ⋅ 点赞:(0)

Kotlin 提供了几种用于操作整数各个位(bit) 的运算符。这些操作是由处理器直接支持的,速度快且操作简单。在底层编程中非常重要,比如设备驱动、低级图形处理、网络通信、加密和压缩等。

尽管计算机通常都有高效的硬件指令来执行算术和逻辑操作,但所有这些操作也都可以通过组合按位操作符位移操作符判断 0 操作来实现。


位运算符(Bitwise Operators)

共有四种位运算符:

  • inv():按位非(NOT),即取反或补码

  • or:按位或(OR)

  • and:按位与(AND)

  • xor:按位异或(XOR)

这些运算符会一位一位地处理操作数的每一位,并生成一个新的数值。

  • inv() 是一元运算符,它会将每一位的 0 变为 1,1 变为 0(包括符号位也会改变)。

  • or 是二元运算符,按位“或”:只要任意一个操作数为 1,结果就是 1,否则是 0。

  • and 是按位“与”:只有两个操作数都为 1,结果才是 1,否则是 0。

  • xor 是按位“异或”:当两个操作数中正好一个为 1 时,结果是 1,否则是 0。

这些运算符不仅可以作用于整数,也可以作用于布尔类型。如果是整数,进行的是位运算;如果是布尔值,进行的是逻辑运算(除了 inv() 不能用于布尔类型)。


示例:按位与、或、异或

val first = 15  // 二进制:1111
val second = 10 // 二进制:1010

val bitwiseAnd = first and second // 1111 & 1010 = 1010,结果是 10
val bitwiseOr = first or second   // 1111 | 1010 = 1111,结果是 15
val bitwiseXor = first xor second // 1111 ^ 1010 = 0101,结果是 5

示例:按位取反(inv)

val first = 35   // 二进制:0..00100011
val second = -35 // 二进制:1..11011101(补码)

val inverseFirst = first.inv()     // ~35 = -36
val inverseSecond = second.inv()   // ~-35 = 34

为什么 ~35 = -36?这是因为 Kotlin 使用**补码(two’s complement)**来表示整数。

  • 对任意正整数 n,其按位取反是 -(n + 1)

  • 对负数 -n,其按位取反是 n - 1


检查一个数是否能被 2 整除(使用 and

val a = 5
val b = 4

val bitwiseAndA = a and 1 // 101 & 001 = 001,结果是 1 => 有余数,不能整除
val bitwiseAndB = b and 1 // 100 & 001 = 000,结果是 0 => 没有余数,可以整除

位移操作符(Bit-shift Operators)

Kotlin 还提供了三种位移操作符:

  • shl:左移(乘法),低位补零;

  • shr:带符号右移,高位填符号位(保留正负号);

  • ushr:无符号右移,高位补零(结果永远为正)。

示例:通过位移实现快速乘除法

var value = 25   // 二进制:0001 1001

value = value shl 1 // 左移1位:0011 0010 => 50
value = value shl 2 // 再左移2位:1100 1000 => 200

var anotherVal = 14
anotherVal = anotherVal shr 1 // 右移1位:0111 => 7

我们可以总结出:

var newVal = 25

newVal = newVal shl 1 // 25 * 2^1 = 50
newVal = newVal shl 3 // 50 * 2^3 = 400
newVal = newVal shr 2 // 400 / 2^2 = 100

示例:使用位移求区间中点

val left = 10
val right = 20

val mid = (left + right) shr 1 // 结果是 15

(left + right) / 2 相同,但位移方式更快。


示例:shrushr 的区别

val number1 = 5
val number2 = -5

val shrNumber1 = number1 shr 1     // 0101 → 0010,结果是 2
val ushrNumber1 = number1 ushr 1   // 同上,结果是 2
val shrNumber2 = number2 shr 1     // 保留符号,结果是 -3
val ushrNumber2 = number2 ushr 1   // 补零,结果是 2147483645
  • shr 会根据符号保留符号位。

  • ushr 总是左边补 0,所以负数也变为正数。


Kotlin 1.6 新增:位旋转

val a = 4

val shiftRight = a.rotateRight(1) // 0100 → 0010,结果是 2
val shiftLeft = a.rotateLeft(1)   // 0100 → 1000,结果是 8
val b = 3

val shiftLeft = b.rotateLeft(1)   // 0011 → 0110,结果是 6
val shiftRight = b.rotateRight(1) // 0011 → 1..0001,结果是 -2147483647

rotateRight 会把最高位 1 移到符号位(第 31 位),结果变成负数。


运算优先级

Kotlin 中,位运算符和位移运算符的优先级低于加减乘除:

优先级(从高到低) 运算符例子
括号 (expr)
后缀自增自减 expr++, expr--
前缀正负、自增自减 -expr, ++expr, --expr
乘、除、模 *, /, %
加减 +, -
赋值及其组合 =, +=, -=, *=
位运算和位移 and, or, xor, shl, shr, ushr
位运算符之间是从左到右执行的。

例如:

val mid = left + right shr 1

无需加括号,是因为 + 的优先级高于 shr,相当于:

val mid = (left + right) shr 1

总结

在本节中,我们学习了如何对整数的进行操作,理解了位运算与一些算术运算之间的对应关系:

  • 位运算符:逐位处理。

  • 位移运算符:可以整体左移或右移一整串位。
    虽然位运算看起来稍显复杂,但这是理解底层编程和高效计算的基础。


网站公告

今日签到

点亮在社区的每一天
去签到