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两个新手必踩的坑:
- 整数除整数:结果是整数,小数部分被舍弃。
7 / 2是3,不是3.5。 - 负数除法向下取整:
-7 / 2是-4(向负无穷),不是-3(向零)。这是因为 Ruby 的除法统一是"向下取整"。
2. 比较运算符
比较运算符返回 true 或 false:
# 比较运算符:返回 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(飞船)<=>,返回 -1、0 或 1。它主要用在自定义排序——sort 方法默认就用它。一旦你写类时实现了 <=> 方法,你的对象就能直接用 sort、min、max。
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 优先级低(低于赋值)。社区约定:
- 布尔表达式用
&&、||、!。 - 控制流用
and、or(如do_something or raise "失败")。
短路求值的两个惯用法很常用:
- 设默认值:
name = params[:name] || "匿名"。 - 守卫:
user.admin? && show_admin_panel。
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 运算符优先级从高到低(只列常用的):
!(最高,一元)**(乘方)- 一元
-+ */%+-<<>>&|^<=>==!=&&||.....? :(三元)=(赋值,最低之一)notandor(最低)
记不住没关系,实际写代码时不确定就加括号,这是最稳妥的做法。
小结
本章覆盖了 Ruby 全部常用运算符。最该记住的几个点:整数除法向下取整、|| 用来设默认值、spaceship 用于排序、defined? 用于判断定义。下一篇我们看控制流——让程序能做判断、能循环。
← 上一篇 Ruby 数据类型
下一篇 Ruby 控制流 →