Kotlin位运算

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() 不能用于布尔类型)。


示例:按位与、或、异或

kotlin 复制代码
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)

kotlin 复制代码
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

kotlin 复制代码
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:无符号右移,高位补零(结果永远为正)。

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

kotlin 复制代码
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

我们可以总结出:

kotlin 复制代码
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

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

kotlin 复制代码
val left = 10
val right = 20

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

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


示例:shrushr 的区别

kotlin 复制代码
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 新增:位旋转

kotlin 复制代码
val a = 4

val shiftRight = a.rotateRight(1) // 0100 → 0010,结果是 2
val shiftLeft = a.rotateLeft(1)   // 0100 → 1000,结果是 8
kotlin 复制代码
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
位运算符之间是从左到右执行的。

例如:

kotlin 复制代码
val mid = left + right shr 1

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

kotlin 复制代码
val mid = (left + right) shr 1

总结

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

  • 位运算符:逐位处理。

  • 位移运算符 :可以整体左移或右移一整串位。

    虽然位运算看起来稍显复杂,但这是理解底层编程和高效计算的基础。

相关推荐
小羊没烦恼!9 小时前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
千里马学框架9 小时前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台9 小时前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone10 小时前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
伞伞悦读10 小时前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
致远ccc10 小时前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
C语言小火车11 小时前
C/C++ 为什么需要编译器?
开发语言·c++
霍霍的袁12 小时前
【C++】map 和 set 的使用 | 从用法到底层
开发语言·c++·学习·visual studio
ttyyttemo12 小时前
Kotlin 协程中的 Job 结构化并发与取消
android
孙启超12 小时前
【AI开发之Rust】第 11 课:智能指针与内部可变性
开发语言·后端·rust