Ruby 运算符

运算符是程序里"操作数据"的工具——加、减、比较、判断。本章把 Ruby 常用运算符分六类讲一遍,重点说清楚几个易踩坑的细节和 Ruby 独有的特性。

1. 算术运算符

最基础的四则运算、乘方、取余:

# 算术运算符
puts 7 + 2      # 9
puts 7 - 2      # 5
puts 7 * 2      # 14
puts 7 / 2      # 3(整数除法,向下取整)
puts 7 % 2      # 1(取余)
puts 7 ** 2     # 49(乘方)
puts 7.0 / 2    # 3.5(浮点除法)
puts -7 / 2     # -4(注意:Ruby 向负无穷取整,不是向零)

# 整数除法注意:Ruby 是"向下取整",不是"向零截断"
puts (-7) / 2      # -4(不是 -3)
puts (-7).fdiv(2)  # -3.5

两个新手必踩的坑:

2. 比较运算符

比较运算符返回 truefalse:

# 比较运算符:返回 true 或 false
puts 3 == 3     # true
puts 3 != 4     # true
puts 3 < 5      # true
puts 3 > 5      # false
puts 3 <= 3     # true
puts 3 >= 4     # false

# 字符串也能比较(按字典序)
puts "apple" < "banana"   # true
puts "abc" == "abc"        # true

# Ruby 特有的 spaceship 操作符 <=>
puts (1 <=> 2)   # -1(左边小)
puts (2 <=> 2)   # 0(相等)
puts (3 <=> 2)   # 1(左边大)

Ruby 有个独有运算符叫 spaceship(飞船)<=>,返回 -101。它主要用在自定义排序——sort 方法默认就用它。一旦你写类时实现了 <=> 方法,你的对象就能直接用 sortminmax

3. 逻辑运算符

Ruby 的逻辑运算符有两套——符号形式和英文单词形式:

# 逻辑运算符
puts true && false    # false(与)
puts true || false    # true(或)
puts !true            # false(非)

# 字词形式(优先级更低,但更可读)
puts true and false   # 注意:and 优先级低于 &&
puts true or false    # or 优先级低于 ||

# 短路求值(常用作"默认值"和"无副作用判断")
name = nil
puts name || "匿名"     # 匿名(name 为 nil 时取后者)

# && 还常做"守卫"——前条件成立才执行
config = { debug: true }
config[:debug] && puts("调试信息")

两套的区别是优先级:&& / || 优先级高,and / or 优先级低(低于赋值)。社区约定:

短路求值的两个惯用法很常用:

4. 赋值运算符

# 赋值运算符
a = 10
a += 5     # a = a + 5 → 15
a -= 3     # 12
a *= 2     # 24
a /= 4     # 6
a **= 2    # 36
a %= 5     # 1

# 多重赋值
x, y, z = 1, 2, 3

# 复合赋值也支持数组连接
arr = [1]
arr <<= 2         # [1, 2](追加)
arr <<= [3, 4]    # [1, 2, [3, 4]]

复合赋值(+=-= 等)和大多数语言一致。Ruby 多了 <<= 用于追加到数组(等价于 arr.push)。

5. 位运算

位运算直接操作二进制位,日常 Web 开发用得少,但在权限系统、压缩算法、嵌入式等场景常用:

# 位运算(对整数)
puts 5 & 3      # 1(按位与)
puts 5 | 3      # 7(按位或)
puts 5 ^ 3      # 6(按位异或)
puts ~5         # -6(按位取反)
puts 5 << 1     # 10(左移一位 = 乘 2)
puts 20 >> 2    # 5(右移两位 = 除 4)

一个经典用法是位掩码权限:用每个 bit 表示一种权限,用按位或叠加、按位与检查。

6. 范围与三元运算符

# 范围运算符
r1 = 1..5       # 闭区间 [1, 5]
r2 = 1...5      # 半开区间 [1, 5)

puts r1.to_a.inspect    # [1, 2, 3, 4, 5]
puts r2.to_a.inspect    # [1, 2, 3, 4]

# ternary 三元运算符(和 C/JS 一样)
age = 20
puts age >= 18 ? "成年" : "未成年"   # 成年

范围运算符 ..... 的差异:前者包含末尾,后者不含。三元运算符 条件 ? 真值 : 假值 和 C/JS 完全一致。

7. defined? 特殊运算符

Ruby 有个独有运算符 defined?,判断某物是否定义。它不是返回 true/false,而是返回一个描述字符串或 nil:

# defined? 是个特殊运算符:判断某物是否定义
x = 10
puts defined?(x)         # "local-variable"
puts defined?(y)         # nil(y 没定义)
puts defined?(puts)      # "method"
puts defined?(@foo)      # "instance-variable"(即使为 nil)

# 用于方法可选参数判断
def greet(name)
  name = "匿名" unless defined?(name) && name
  puts "你好"
end

它和 nil? 的区别是:defined?(@foo) 即使 @foo 是 nil 也会返回 "instance-variable",因为它检查的是定义本身,不是值。

8. 运算符优先级

Ruby 运算符优先级从高到低(只列常用的):

记不住没关系,实际写代码时不确定就加括号,这是最稳妥的做法。

小结

本章覆盖了 Ruby 全部常用运算符。最该记住的几个点:整数除法向下取整、|| 用来设默认值、spaceship 用于排序、defined? 用于判断定义。下一篇我们看控制流——让程序能做判断、能循环。

← 上一篇 Ruby 数据类型

下一篇 Ruby 控制流

✈️💬