原文: https://zetcode.com/lang/rubytutorial/expressions/

在 Ruby 教程的这一部分中,我们将讨论表达式。

表达式是根据操作数和运算符构造的。 表达式的运算符指示将哪些运算应用于操作数。 表达式中运算符的求值顺序由运算符的优先级和关联性确定。

运算符是特殊符号,表示已执行某个过程。 编程语言的运算符来自数学。 程序员处理数据。 运算符用于处理数据。 操作数是运算符的输入(参数)之一。

Ruby 运算符

下表显示了按优先级排序的常见 Ruby 运算符(优先级最高):

类别 符号
解析,访问运算符 :: .
数组运算符 [ ] [ ]=
乘方 **
否定,补码,一元加,减 ! ~ + -
乘,除,模 * / %
加,减 + -
移位运算符 << >>
按位与 &
按位异或,逻辑异或 ^ &#124;
关系运算符 > >= < <=
按位或,逻辑或 ^ &#124;
相等,模式匹配运算符 <=> == === != =~ !~
逻辑与 &&
逻辑或 ` `
范围运算符 .. ...
三元 ?:
赋值运算符 = += -= *= **= /= %= &= &#124;= ^= <<= >>= &#124;&#124;= &&=
备选逻辑非 not
备选逻辑或,与 or and

表的同一行上的运算符具有相同的优先级。

一个运算符通常有一个或两个操作数。 那些仅使用一个操作数的运算符称为一元运算符。 那些使用两个操作数的对象称为二进制运算符。 还有一个三元运算符?:,它可以处理三个操作数。

某些运算符可以在不同的上下文中使用。 例如+运算符。 从上表中我们可以看到它在不同情况下使用。 它添加数字,连接字符串,指示数字的符号。 我们说运算符是重载。

Ruby 符号运算符

有两个符号运算符:+-。 它们用于指示或更改值的符号。

  1. #!/usr/bin/ruby
  2. puts +2
  3. puts -2

+和-表示值的符号。 加号可以用来表示我们有一个正数。 可以将其省略,并且通常可以这样做。

在下面的示例中,我们将使用减号。

  1. #!/usr/bin/ruby
  2. a = 1
  3. puts a
  4. puts -(a)
  5. puts -(-(a))

减号更改值的符号。

  1. $ ./sign.rb
  2. 1
  3. -1
  4. 1

这是示例的输出。

Ruby 赋值运算符

赋值运算符=将值赋给变量。 变量是值的占位符。 在数学中,=运算符具有不同的含义。 在等式中,=运算符是一个相等运算符。 等式的左侧等于右侧。

  1. x = 1
  2. puts x # prints 1

在这里,我们为x变量分配一个数字。

  1. x = x + 1
  2. puts x # prints 2

先前的表达式在数学上没有意义。 但这在编程中是合法的。 该表达式将x变量加 1。 右边等于 2,并且 2 分配给x

  1. 3 = x;

此代码示例导致语法错误。 我们无法为字面值分配值。

Ruby 解析,成员访问运算符

这两个运算符的优先级最高。 这意味着始终要首先求值它们。

  1. #!/usr/bin/ruby
  2. class MyMath
  3. Pi = 3.1415926535
  4. end
  5. module People
  6. Name = "People"
  7. end
  8. puts MyMath::Pi
  9. puts People::Name

在第一个示例中,我们介绍::名称空间解析运算符。 它允许访问在另一个类或模块内定义的常量,模块或类。 它用于提供名称空间,以使方法和类名不会与不同作者的其他类冲突。

  1. class MyMath
  2. Pi = 3.1415926535
  3. end
  4. module People
  5. Name = "People"
  6. end

我们有一个简单的模块和一个类。 每个都有一个定义的常数。

  1. puts MyMath::Pi
  2. puts People::Name

我们使用::运算符从这两者访问常量。

  1. $ ./resolution.rb
  2. 3.1415926535
  3. People

这是resolution.rb程序的输出。

.运算符是成员访问运算符。 它用于调用对象的方法。

  1. #!/usr/bin/ruby
  2. class Person
  3. def initialize name, age
  4. @name = name
  5. @age = age
  6. end
  7. def info
  8. "#{@name} is #{@age} years old"
  9. end
  10. end
  11. p = Person.new "Jane", 17
  12. puts p.info
  13. puts "ZetCode".reverse

在我们的示例中,我们有两个对象。 一位用户定义和一位预定义。 我们使用点运算符来处理这些对象。

  1. p = Person.new "Jane", 17
  2. puts p.info

在这两行中,点运算符调用两种方法:newinfo

  1. puts "ZetCode".reverse

字符串是内置对象,具有反向方法。 这被称为。

  1. $ ./memberaccess.rb
  2. Jane is 17 years old
  3. edoCteZ

这是示例的输出。

Ruby 连接字符串

在 Ruby 中,+运算符还用于连接字符串。 当在不同的上下文中不同地使用运算符时,我们说它是重载。

  1. #!/usr/bin/ruby
  2. puts "Return " + "of " + "the " + "King"
  3. puts "Return ".+"of ".+ "the ".+"King"

我们使用字符串连接运算符将三个字符串连接在一起。

  1. puts "Return " + "of " + "the " + "King"

我们使用+运算符连接四个字符串。

  1. puts "Return ".+"of ".+ "the ".+"King"

在后台,+运算符是 Ruby 方法。 字符串字面值是一个对象。 我们使用访问.运算符调用对象的方法。

  1. $ ./catstrings.rb
  2. Return of the King
  3. Return of the King

这就是我们运行catstrings.rb程序时得到的。

Ruby 自增自减运算符

Ruby 没有此类运算符。

  1. x++;
  2. x = x + 1;
  3. ...
  4. y--;
  5. y = y - 1;

这些是 C 中的递增,递减运算符。

如果您熟悉 Java,C,C++ ,则知道这些运算符。 它们在 Ruby 中不可用。 Python 语言也没有。

Ruby 算术运算符

下表是 Ruby 中的算术运算符表。

符号 名称
+ 加法
- 减法
* 乘法
/ 除法
% 余数
** 乘方

在下一个示例中,我们使用算术运算。

  1. #!/usr/bin/ruby
  2. a = 10
  3. b = 11
  4. c = 12
  5. puts a + b + c
  6. puts c - a
  7. puts a * b
  8. puts c / 3
  9. puts c % a
  10. puts c ** a

在前面的示例中,我们使用加法,减法,乘法,除法和余数运算。 这些都是数学所熟悉的。

  1. puts c % a

% 运算符称为余数或取模运算符。 它找到一个数除以另一个的余数。 例如,9 % 4,9 模 4 为 1,因为 4 两次进入 9 且余数为 1。

  1. $ ./arithmetic.rb
  2. 33
  3. 2
  4. 110
  5. 4
  6. 2
  7. 61917364224

This is the output of the example.

接下来,我们将说明整数除法和浮点除法之间的区别。

  1. #!/usr/bin/ruby
  2. puts 5 / 2
  3. puts 5 / 2.0
  4. puts 5.0 / 2
  5. puts 5.to_f / 2

在前面的示例中,我们将两个数字相除。

  1. puts 5 / 2

表达式中的两个操作数都是整数。 我们已经完成了整数除法。 除法运算的返回值为整数。 当我们将两个整数相除时,结果是一个整数。

  1. puts 5 / 2.0
  2. puts 5.0 / 2
  3. puts 5.to_f / 2

如果其中一个值是浮点数(或两者皆有),则执行浮点除法。 浮点值具有小数点。 我们还可以调用to_f方法将整数转换为浮点数。

  1. $ ./division.rb
  2. 2
  3. 2.5
  4. 2.5
  5. 2.5

在这里,我们看到了division.rb程序的结果。

Ruby 还有其他执行除法的方法。 这些可用作方法调用。

  1. #!/usr/bin/ruby
  2. puts 5.div 2.0
  3. puts 5.fdiv 2
  4. puts 5.quo 2
  5. puts 5.0.quo 2.0

在上面的示例中,我们有divfdivquo方法。

  1. puts 5.div 2.0

div方法始终执行整数除法。 即使操作数是浮点值。

  1. puts 5.fdiv 2

fdiv方法始终执行浮点除法。

  1. puts 5.quo 2
  2. puts 5.0.quo 2.0

quo方法执行最精确的划分。 如果两个操作数均为float,则返回float,否则返回有理数。

  1. $ ./otherdivision.rb
  2. 2
  3. 2.5
  4. 5/2
  5. 2.5

Ruby 布尔运算符

在 Ruby 中,我们具有以下逻辑运算符。 布尔运算符也称为逻辑运算符。

符号 名称
&& 逻辑与
` ` 逻辑或
! 否定

布尔运算符处理真值。 Ruby 还有其他的布尔运算符。 这些是andor & not。 除了它们的优先级较低之外,它们的作用相同。 这种双重性来自 Perl 语言,在这种语言中,需要使用具有较低优先级的布尔运算符。

  1. #!/usr/bin/ruby
  2. x = 3
  3. y = 8
  4. puts x == y
  5. puts y > x
  6. if y > x then
  7. puts "y is greater than x"
  8. end

许多表达式导致布尔值。 布尔值用于条件语句中。

  1. puts x == y
  2. puts y > x

关系运算符始终导致布尔值。 这两行分别显示falsetrue

  1. if y > x then
  2. puts "y is greater than x"
  3. end

仅在满足括号内的条件时才执行if语句的主体。 表达式x > y返回true,因此消息"y大于x"被打印到终端。

下一个示例显示逻辑and运算符。

  1. #!/usr/bin/ruby
  2. puts true && true
  3. puts true && false
  4. puts false && true
  5. puts false && false

仅当两个操作数均为true时,and运算符的计算结果才为true

  1. $ ./andoperator.rb
  2. true
  3. false
  4. false
  5. false

仅其中一个表达式为true

如果两个操作数中的任何一个为true,则逻辑或||运算符的计算结果为true

  1. #!/usr/bin/ruby
  2. puts true || true
  3. puts true || false
  4. puts false || true
  5. puts false || false

如果运算符的任一侧为真,则操作的结果为真。

  1. $ ./oroperator.rb
  2. true
  3. true
  4. true
  5. false

三个表达式得出布尔值true

否定!表示真假和假真。

  1. #!/usr/bin/ruby
  2. puts !0
  3. puts !1
  4. puts !true
  5. puts !false
  6. puts ! (4<3)
  7. puts ! "Ruby".include?("a")

该示例显示了否定运算符的作用。

  1. $ ./not.rb
  2. false
  3. false
  4. false
  5. true
  6. true
  7. true

This is the output of the example.

||&&运算符经过短路求值。 短路求值意味着仅当第一个参数不足以确定表达式的值时才求值第二个参数:当逻辑的第一个参数的值等于false时,总值必须为false; 当逻辑或的第一个参数为true时,总值必须为true。 短路求值主要用于提高性能。

一个例子可以使这一点更加清楚。

  1. #!/usr/bin/ruby
  2. def one
  3. puts "Inside one"
  4. false
  5. end
  6. def two
  7. puts "Inside two"
  8. true
  9. end
  10. puts "Short circuit"
  11. if one && two
  12. puts "Pass"
  13. end
  14. puts "##############################"
  15. if two || one
  16. puts "Pass"
  17. end

在示例中,我们有两种方法。 它们在布尔表达式中用作操作数。 我们将看看它们是否被调用。

  1. if one && two
  2. puts "Pass"
  3. end

一种方法返回false。 短路&&无法求值第二种方法。 没有必要。 一旦操作数为假,逻辑结论的结果始终为假。 仅将"Inside one"打印到控制台。

  1. puts "##############################"
  2. if two || one
  3. puts "Pass"
  4. end

在第二种情况下,我们使用||运算符,并使用two方法作为第一个操作数。 在这种情况下,"Inside two""Pass"字符串将打印到终端。 同样,也不必求值第二个操作数,因为一旦第一个操作数计算为true,则逻辑或始终为true

  1. $ ./shortcircuit.rb
  2. Short circuit
  3. Inside one
  4. ##############################
  5. Inside two
  6. Pass

我们看到了shortcircuit.rb程序的结果。

Ruby 关系运算符

关系运算符用于比较值。 这些运算符总是产生布尔值。

符号 含义
< 小于
<= 小于或等于
> 大于
>= 大于或等于

关系运算符也称为比较运算符。

  1. #!/usr/bin/ruby
  2. p 3 < 4
  3. p 3 > 5
  4. p 3 >= 3

3 < 4表达式返回true,因为 3 小于 4。3 > 5表达式返回false,因为 3 大于 5 并不成立。

Ruby 按位运算符

小数对人类是自然的。 二进制数是计算机固有的。 二进制,八进制,十进制或十六进制符号仅是相同数字的符号。 按位运算符使用二进制数的位。

符号 含义
~ 按位取反
^ 按位异或
& 按位与
` ` 按位或
<< 左移
>> 右移

很少在像 Ruby 这样的高级语言中使用按位运算符。

  1. #!/usr/bin/ruby
  2. puts ~ 7 # prints -8
  3. puts ~ -8 # prints 7
  4. puts 6 & 3 # prints 2
  5. puts 3 & 6 # prints 2
  6. puts 6 ^ 3 # prints 5
  7. puts 3 ^ 6 # prints 5
  8. puts 6 | 3 # prints 7
  9. puts 3 | 6 # prints 7
  10. puts 6 << 1 # prints 12
  11. puts 1 << 6 # prints 64
  12. puts 6 >> 1 # prints 3
  13. puts 1 >> 6 # prints 0

在上面的代码示例中,我们显示了所有 6 个运算符。

  1. puts ~ 7 # prints -8
  2. puts ~ -8 # prints 7

按位取反运算符分别将 1 更改为 0,将 0 更改为 1。该运算符还原数字 7 的所有位。其中一位还确定数字是否为负。 如果我们再一次对所有位取反,我们将再次得到 7。

  1. puts 6 & 3 # prints 2
  2. puts 3 & 6 # prints 2

按位,运算符在两个数字之间进行逐位比较。 仅当操作数中的两个对应位均为 1 时,位位置的结果才为 1。

  1. puts 6 ^ 3 # prints 5
  2. puts 3 ^ 6 # prints 5

按位互斥或运算符在两个数字之间进行逐位比较。 如果操作数中对应位中的一个或另一个(但不是全部)为 1,则位位置的结果为 1。

  1. puts 6 | 3 # prints 7
  2. puts 3 | 6 # prints 7

按位或运算符在两个数字小体之间进行逐位比较。 如果操作数中的任何对应位为 1,则位位置的结果为 1。

  1. puts 6 << 1 # prints 12
  2. puts 1 << 6 # prints 64
  3. puts 6 >> 1 # prints 3
  4. puts 1 >> 6 # prints 0

按位移位运算符向右或向左移位。 这些运算符也称为算术移位。

Ruby 复合赋值运算符

复合赋值运算符由两个运算符组成。 他们是速记员。

  1. #!/usr/bin/ruby
  2. a = 0
  3. a = a + 1
  4. a += 1
  5. puts a
  6. b = 0
  7. b = b - 8
  8. b -= 8
  9. puts b

+=-=复合运算符是这些速记运算符之一。 它们比完整的表达式可读性差,但是经验丰富的程序员经常使用它们。

  1. a = a + 1
  2. a += 1

这两行是相同的。 他们将 1 加到变量。

其他复合运算符是:

  1. -= *= **= /= %= &= |= <<= >>=

Ruby 运算符优先级

运算符优先级告诉我们首先求值哪个运算符。 优先级对于避免表达式中的歧义是必要的。

以下表达式 28 或 40 的结果是什么?

  1. 3 + 5 * 5

像数学中一样,乘法运算符的优先级高于加法运算符。 结果是 28。

  1. (3 + 5) * 5

要更改求值的顺序,可以使用括号。 括号内的表达式始终首先被求值。

  1. #!/usr/bin/ruby
  2. puts 3 + 5 * 5
  3. puts (3 + 5) * 5
  4. puts ! true | true
  5. puts ! (true | true)

在此代码示例中,我们显示一些常见的表达式。 每个表达式的结果取决于优先级。

  1. puts 3 + 5 * 5

该行打印 28。乘法运算符的优先级高于加法。 首先计算5*5的乘积。 然后添加 3。

  1. puts ! true | true

在这种情况下,否定运算符具有更高的优先级。 首先,第一个true值与|运算符将falsetrue组合在一起,最后给出true

  1. $ ./precedence.rb
  2. 28
  3. 40
  4. true
  5. false

Ruby 关联性

有时,优先级不能令人满意地确定表达式的结果。 还有另一个规则称为关联性。 运算符的关联性确定优先级与相同的运算符的求值顺序。

  1. 9 / 3 * 3

此表达式的结果是 9 还是 1? 乘法,删除和模运算符从左到右关联。 因此,该表达式的计算方式为:(9 / 3) * 3,结果为 9。

算术,布尔,关系和按位运算符都是从左到右关联的。

另一方面,赋值运算符是正确关联的。

  1. a = b = c = d = 0
  2. print a, b, c, d # prints 0000

如果关联从左到右,则以前的表达式将不可能。

复合赋值运算符从右到左关联。

  1. j = 0
  2. j *= 3 + 1
  3. puts j

您可能期望结果为 1,但是由于关联性,实际结果为 0。 首先求值右边的表达式,然后应用复合赋值运算符。

Ruby 范围运算符

Ruby 有两个范围运算符。 它们用于快速创建一系列对象。 通常是一系列数字或字母。

..范围运算符(两个点)创建一个包含范围。 ...运算符(三个点)创建一个互斥范围,该范围的高值被排除在外。

  1. #!/usr/bin/ruby
  2. p (1..3).to_a
  3. p (1...3).to_a
  4. p ('a' .. 'l').to_a

在示例中,我们使用了两个范围运算符来创建数字和字符的范围。

  1. p (1..3).to_a
  2. p (1...3).to_a

这两行使用两个范围运算符创建两个范围。 范围对象将转换为数组。 第一个范围的值为 1、2 和 3,而第二个范围的值为 1 和 2。

  1. p ('a' .. 'l').to_a

在这里,我们使用..范围运算符来创建从’a’到’l’的字母数组。

  1. $ ./range.rb
  2. [1, 2, 3]
  3. [1, 2]
  4. ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"]

这是示例输出。

Ruby 三元运算符

三元运算符?:是条件运算符。 对于要根据条件表达式选择两个值之一的情况,它是一个方便的运算符。

  1. cond-exp ? exp1 : exp2

如果cond-exptrue,则求值exp1并返回结果。 如果cond-expfalse,则求值exp2并返回其结果。

  1. #!/usr/bin/ruby
  2. age = 32
  3. adult = age >= 18 ? true : false
  4. if adult then
  5. puts "Adult"
  6. else
  7. puts "Not adult"
  8. end

在大多数国家/地区,成年取决于您的年龄。 如果您的年龄超过特定年龄,则您已经成年。 在这种情况下,我们可以使用三元运算符。

  1. adult = age >= 18 ? true : false

首先,求值赋值运算符右侧的表达式。 三元运算符的第一阶段是条件表达式求值。 因此,如果年龄大于或等于 18,则返回?字符后的值。 如果不是,则返回:字符后的值。 然后将返回值分配给成人变量。

  1. $ ./ternary.rb
  2. Adult

32 岁的成年人是成人。

计算素数

我们将计算素数。

  1. #!/usr/bin/ruby
  2. nums = (4..50).to_a
  3. puts "Prime numbers:"
  4. print "2 3 "
  5. nums.each do |i|
  6. not_prime = false
  7. (2..Math.sqrt(i).ceil).each do |j|
  8. not_prime = true if i % j == 0
  9. end
  10. print i, " " unless not_prime
  11. end
  12. puts

在上面的示例中,我们处理了几个运算符。 质数(或质数)是一个自然数,它具有两个截然不同的自然数除数:1 和它本身。 我们拾取一个数字并将其除以数字,从 2 到拾取的数字。 实际上,我们不必尝试所有较小的数字,我们可以将数字除以所选数字的平方根。 该公式将起作用。 在算法的核心,我们使用余数除法运算符,也称为模运算符。

  1. nums = (4..50).to_a

我们将从这些数字计算素数。

  1. print "2 3 "

我们跳过了 2、3 个数字的计算。 他们是素数。

  1. not_prime = false

not_prime是一个标志,指示所选的数字不是素数。 我们假定所选的数字是质数,除非稍后证明。

  1. (2..Math.sqrt(i).ceil).each do |j|
  2. not_prime = true if i % j == 0
  3. end

如果我们仅对小于所讨论数字平方根的数字进行模除,就可以了。 如果余数除法运算符针对任何i值返回 0,则说明该数字不是质数。

  1. print i, " " unless not_prime

如果未设置not_prime标志,我们将打印数字。

上面的示例旨在演示几个运算符。 实际上,存在一种更简单的方法来计算质数。 Ruby 有一个用于计算素数的模块。

  1. #!/usr/bin/ruby
  2. require 'prime'
  3. Prime.each(50) do |i|
  4. print i, " "
  5. end
  6. puts

使用 Ruby 素数模块计算最多 50 个素数的示例。

  1. require 'prime'

我们包括主要模块。

  1. Prime.each(50) do |i|
  2. print i, " "
  3. end

我们计算素数直至上限 -50。

  1. $ ./primes.rb
  2. 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47

从此输出中,我们看到 2 和 50 之间的质数。

在 Ruby 教程的这一部分中,我们介绍了这些表达式。