Ruby Logo

Ruby Operators & Operands

Master Ruby operators including arithmetic, comparison, logical, assignment, ranges, and special operators.

Home Ruby Ruby Operators & Operands

Operators & Operands

Master Ruby's powerful operators including arithmetic, comparison, logical, assignment, and special operators like ranges and parallel assignment.

Arithmetic Operators

What are Arithmetic Operators? These are symbols that perform mathematical calculations on numbers. They're the building blocks of all mathematical operations in Ruby, allowing you to add, subtract, multiply, divide, and perform other mathematical computations.

Understanding Each Operator

Addition (+)

Combines two numbers to get their sum. Works with integers, floats, and even strings (concatenation).

# Examples:
5 + 3 # => 8
"Hello" + " World" # => "Hello World"
Subtraction (-)

Finds the difference between two numbers. The result is the first number minus the second number.

# Examples:
10 - 4 # => 6
3.14 - 1.14 # => 2.0
Multiplication (*)

Multiplies two numbers together. Also works with strings (repetition) and arrays (replication).

# Examples:
6 * 7 # => 42
"Hi" * 3 # => "HiHiHi"
Division (/)

Divides the first number by the second. Integer division returns an integer, float division returns a float.

# Examples:
15 / 3 # => 5
10.0 / 3 # => 3.333...
Modulo (%)

Returns the remainder after division. Useful for checking if numbers are even/odd or for cycling through values.

# Examples:
10 % 3 # => 1
8 % 2 # => 0 (even)
Exponentiation (**)

Raises the first number to the power of the second number. Can handle fractional powers for roots.

# Examples:
2 ** 3 # => 8
9 ** 0.5 # => 3.0 (square root)

Complete Examples

# Addition
puts 5 + 3 # => 8
puts 2.5 + 1.7 # => 4.2

# Subtraction
puts 10 - 4 # => 6
puts 3.14 - 1.14 # => 2.0

# Multiplication
puts 6 * 7 # => 42
puts 2.5 * 4 # => 10.0

# Division
puts 15 / 3 # => 5
puts 10 / 3 # => 3 (integer division)
puts 10.0 / 3 # => 3.3333333333333335

# Modulo (remainder)
puts 10 % 3 # => 1
puts 15 % 4 # => 3

# Exponentiation
puts 2 ** 3 # => 8
puts 5 ** 2 # => 25
puts 9 ** 0.5 # => 3.0 (square root)

Important Notes

  • Integer Division: 10 / 3 returns 3, not 3.33
  • Float Division: Use at least one float: 10.0 / 3
  • Modulo: Returns remainder after division
  • Exponentiation: ** operator for powers

Comparison Operators

What are Comparison Operators? These operators compare two values and return a boolean result (true or false). They're essential for making decisions in your code, controlling program flow, and implementing conditional logic. Ruby provides both equality and relational comparison operators.

Equality Operators

Equality (==)

Checks if two values are equal. Returns true if they have the same value, false otherwise. Works with all data types.

# Examples:
5 == 5 # => true
"hello" == "hello" # => true
5 == "5" # => false (different types)
Inequality (!=)

The opposite of equality. Returns true if values are different, false if they're the same. Also works with all data types.

# Examples:
5 != 3 # => true
"a" != "b" # => true
5 != 5 # => false

Relational Operators

Less Than (<)

Checks if the left value is less than the right value. Works with numbers, strings (alphabetical order), and dates.

# Examples:
5 < 10 # => true
"apple" < "banana" # => true
Greater Than (>)

Checks if the left value is greater than the right value. Also works with numbers, strings, and dates.

# Examples:
15 > 10 # => true
"zebra" > "apple" # => true
Less Than or Equal (<=)

Checks if the left value is less than or equal to the right value. Includes equality in the comparison.

# Examples:
5 <= 5 # => true
3 <= 5 # => true
7 <= 5 # => false
Greater Than or Equal (>=)

Checks if the left value is greater than or equal to the right value. Includes equality in the comparison.

# Examples:
10 >= 10 # => true
15 >= 10 # => true
8 >= 10 # => false

The Spaceship Operator (<=>)

What is the Spaceship Operator? This is Ruby's three-way comparison operator. It returns -1, 0, or 1 depending on whether the left operand is less than, equal to, or greater than the right operand. It's incredibly useful for sorting and implementing comparison logic.

# Equality
puts 5 == 5 # => true
puts "hello" == "hello" # => true
puts 5 == "5" # => false (different types)

# Inequality
puts 5 != 3 # => true
puts "a" != "b" # => true

# Less than / Greater than
puts 5 < 10 # => true
puts 15 > 10 # => true
puts 5 <= 5 # => true
puts 10 >= 15 # => false

# Spaceship operator (three-way comparison)
puts 5 <=> 3 # => 1 (greater)
puts 3 <=> 5 # => -1 (less)
puts 5 <=> 5 # => 0 (equal)
puts "a" <=> "b" # => -1
puts "z" <=> "a" # => 1

Spaceship Operator <=>

The spaceship operator returns -1, 0, or 1 depending on whether the left operand is less than, equal to, or greater than the right operand. Very useful for sorting!

Assignment & Parallel Assignment

Basic Assignment

# Simple assignment
x = 5
name = "Ruby"

# Compound assignment
x = 10
x += 5 # x = x + 5 => 15
x -= 3 # x = x - 3 => 12
x *= 2 # x = x * 2 => 24
x /= 4 # x = x / 4 => 6
x %= 5 # x = x % 5 => 1
x **= 3 # x = x ** 3 => 1

Parallel Assignment

# Multiple assignment
a, b, c = 1, 2, 3
puts a # => 1
puts b # => 2
puts c # => 3

# Swapping variables
x = 10
y = 20
x, y = y, x # Swap values
puts x # => 20
puts y # => 10

# Array unpacking
arr = [1, 2, 3, 4, 5]
first, second, *rest = arr
puts first # => 1
puts second # => 2
p rest # => [3, 4, 5]

# Ignoring values
_, important, _ = [1, 2, 3]
puts important # => 2

Parallel Assignment Magic

  • Splat operator (*) collects remaining elements
  • Underscore (_) conventionally ignores values
  • Elegant swapping without temporary variables
  • Method returns can be unpacked directly

Logical Operators

# AND operator (&&)
puts true && true # => true
puts true && false # => false
puts 5 > 3 && 10 < 20 # => true

# OR operator (||)
puts true || false # => true
puts false || false # => false
puts 5 > 10 || 3 < 5 # => true

# NOT operator (!)
puts !true # => false
puts !false # => true
puts !(5 > 3) # => false

# Word operators (lower precedence)
puts true and true # => true
puts true or false # => true
puts not true # => false

Short-Circuit Evaluation

&& stops at first false
|| stops at first true

Precedence Difference

&&, || have higher precedence than and, or

Range Operators

# Inclusive range (..)
range1 = (1..5) # includes 1, 2, 3, 4, 5
puts range1.to_a # => [1, 2, 3, 4, 5]
puts range1.include?(5) # => true

# Exclusive range (...)
range2 = (1...5) # includes 1, 2, 3, 4 (excludes 5)
puts range2.to_a # => [1, 2, 3, 4]
puts range2.include?(5) # => false

# String ranges
letters = ('a'..'e')
puts letters.to_a # => ["a", "b", "c", "d", "e"]

# Range operations
puts (1..10).cover?(5) # => true (faster than include?)
puts (1..10).first # => 1
puts (1..10).last # => 10
puts (1..10).size # => 10

# Ranges in case statements
score = 85
grade = case score
when 90..100 then "A"
when 80..89 then "B"
when 70..79 then "C"
else "F"
end
puts grade # => "B"

Range Use Cases

  • Array slicing: arr[1..3]
  • Iteration: (1..10).each { |i| puts i }
  • Case conditions: Pattern matching with ranges
  • String slicing: str[0..4]

Special Operators

# Ternary operator (conditional)
age = 18
status = age >= 18 ? "adult" : "minor"
puts status # => "adult"

# Safe navigation operator (&.)
user = nil
puts user&.name # => nil (no error)
# puts user.name # => NoMethodError

user = { name: "John" }
puts user&.[](:name) # => "John"

# Splat operator (*)
arr = [1, 2, 3]
puts [0, *arr, 4] # => [0, 1, 2, 3, 4]

def method(a, b, c)
puts "#{a}, #{b}, #{c}"
end
method(*arr) # => "1, 2, 3"

# Double splat operator (**)
options = { color: "red", size: "large" }
def create_item(name, **opts)
puts "#{name}: #{opts}"
end
create_item("shirt", **options)
# => "shirt: {:color=>"red", :size=>"large"}"

# Match operator (=~)
puts "hello" =~ /ell/ # => 1 (position of match)
puts "hello" =~ /xyz/ # => nil (no match)

# Case equality operator (===)
puts (1..10) === 5 # => true
puts String === "hello" # => true
puts /abc/ === "abcdef" # => true

Special Operator Notes

  • Safe navigation (&.) prevents NoMethodError on nil
  • Splat (*) expands arrays into arguments
  • Double splat (**) expands hashes into keyword arguments
  • Case equality (===) used internally by case statements

Operation Ordering (Precedence)

Precedence Table (Highest to Lowest)

Priority Operators Description
1 (Highest) ! Logical NOT
2 ** Exponentiation
3 +, -, ~ Unary plus, minus, complement
4 *, /, % Multiplication, division, modulo
5 +, - Addition, subtraction
6 <<, >> Bitwise shift
7 & Bitwise AND
8 |, ^ Bitwise OR, XOR
9 >, >=, <, <= Comparison
10 <=>, ==, ===, !=, =~, !~ Equality and pattern matching
11 && Logical AND
12 || Logical OR
13 .., ... Range operators
14 ? : Ternary conditional
15 =, +=, -=, *=, /=, %=, **= Assignment
16 (Lowest) and, or, not Word logical operators

Precedence Examples

# Precedence affects evaluation order
puts 2 + 3 * 4 # => 14 (not 20)
# Equivalent to: 2 + (3 * 4)

puts (2 + 3) * 4 # => 20
# Parentheses override precedence

# Exponentiation has higher precedence
puts 2 ** 3 * 4 # => 32 (not 4096)
# Equivalent to: (2 ** 3) * 4

# Logical operators
puts true || false && false # => true
# Equivalent to: true || (false && false)

# && vs and precedence difference
a = true && false
puts a # => false

b = true and false
puts b # => true
# Equivalent to: (b = true) and false

Best Practices

  • Use parentheses for clarity, even when not required
  • Break complex expressions into multiple lines
  • Prefer && and || over and and or in expressions
  • Use and and or for control flow, not in expressions

Practice Examples

# Calculator with all operator types
def calculate(a, b, operation)
case operation
when :add then a + b
when :subtract then a - b
when :multiply then a * b
when :divide then b != 0 ? a / b : "Cannot divide by zero"
when :power then a ** b
when :modulo then a % b
when :compare then a <=> b
else "Unknown operation"
end
end

# Grade calculator using ranges and ternary
def letter_grade(score)
case score
when 90..100 then "A"
when 80...90 then "B"
when 70...80 then "C"
when 60...70 then "D"
else "F"
end
end

# Safe user data access
def user_info(user)
name = user&.[](:name) || "Unknown"
age = user&.[](:age)
status = age && age >= 18 ? "Adult" : "Minor"
"#{name} (#{status})"
end

# Array manipulation with splat
def merge_arrays(*arrays)
result = []
arrays.each { |arr| result.push(*arr) }
result
end

puts merge_arrays([1, 2], [3, 4], [5])
# => [1, 2, 3, 4, 5]

Try It Yourself - Interactive Practice

Learning Tip: The best way to master operators is through hands-on practice! Try these exercises step by step. Don't worry if you make mistakes - that's how you learn! Start with simple examples and gradually work your way up to more complex ones.

Interactive Code Runner

Ruby Code Editor
Output will appear here when you run the code...

Step-by-Step Practice Exercises

Exercise 1
Basic Arithmetic Calculator

Goal: Create a simple calculator that performs basic arithmetic operations.

# Step 1: Try these basic operations
puts 10 + 5
puts 20 - 8
puts 4 * 6
puts 15 / 3
puts 17 % 5
puts 2 ** 4

Learning Tip: Copy this code into the editor above and run it. Then try changing the numbers and see what happens! Experiment with different values to understand how each operator works.

Exercise 2
Variable Swapping Magic

Goal: Learn how to swap variable values without using a temporary variable.

# Step 1: Create two variables
name1 = "Alice"
name2 = "Bob"
puts "Before swap: #{name1} and #{name2}"

# Step 2: Swap them using parallel assignment
name1, name2 = name2, name1
puts "After swap: #{name1} and #{name2}"

# Step 3: Try with numbers too!
a, b = 100, 200
puts "Numbers before: #{a}, #{b}"
a, b = b, a
puts "Numbers after: #{a}, #{b}"

Why This Matters: In most programming languages, you need a temporary variable to swap values. Ruby's parallel assignment makes this elegant and simple!

Exercise 3
Range Operations

Goal: Understand the difference between inclusive (..) and exclusive (...) ranges.

# Inclusive range (includes the last number)
inclusive = (1..5)
puts "Inclusive (1..5): #{inclusive.to_a}"
puts "Does it include 5? #{inclusive.include?(5)}"

# Exclusive range (excludes the last number)
exclusive = (1...5)
puts "Exclusive (1...5): #{exclusive.to_a}"
puts "Does it include 5? #{exclusive.include?(5)}"

# String ranges work too!
letters = ('a'..'e')
puts "Letters: #{letters.to_a}"

Key Insight: Notice the difference between two dots (..) and three dots (...). This small difference changes whether the last number is included or not!

Exercise 4
Safe Navigation Practice

Goal: Learn how to safely access object properties without causing errors.

# Safe navigation prevents errors when object is nil
user = nil
puts "Safe access: #{user&.name || 'No user found'}"

# Now try with a real user
user = { name: "Alice", age: 25 }
puts "User name: #{user&.[](:name)}"
puts "User age: #{user&.[](:age)}"

# Try accessing a non-existent key
puts "User email: #{user&.[](:email) || 'No email'}"

Important: Without the safe navigation operator (&.), trying to access properties on nil would cause an error. This operator makes your code more robust!

Real-World Use Cases

Why This Matters: Understanding operators isn't just about syntax - it's about solving real problems! Here are practical examples you'll encounter in actual Ruby applications.

E-commerce Price Calculator

Calculate total prices with tax, discounts, and shipping using arithmetic operators.

# Price calculation
base_price = 99.99
tax_rate = 0.08
discount = 10
shipping = 5.99

subtotal = base_price - discount
tax = subtotal * tax_rate
total = subtotal + tax + shipping

puts "Total: $#{total.round(2)}"

User Validation System

Validate user input using comparison operators and logical operators.

# User validation
age = 17
email = "user@example.com"
password_length = 8

valid_age = age >= 18
valid_email = email.include?("@")
valid_password = password_length >= 8

can_register = valid_age && valid_email && valid_password
puts "Can register: #{can_register}"

Data Processing Pipeline

Process arrays of data using ranges and parallel assignment.

# Data processing
scores = [85, 92, 78, 96, 88]
first, second, *rest = scores

puts "Top score: #{first}"
puts "Second: #{second}"
puts "Others: #{rest}"

# Grade ranges
grade = case first
when 90..100 then "A"
when 80...90 then "B"
else "C"
end

Configuration Management

Handle configuration with safe navigation and compound assignment.

# Safe configuration access
config = { timeout: 30, retries: 3 }

timeout = config&.[](:timeout) || 60
retries = config&.[](:retries) || 1

# Compound assignment for counters
attempts = 0
attempts += 1 # Increment counter
puts "Attempt #{attempts} of #{retries}"

Common Mistakes & Learning Tips

Common Mistakes

Mistake 1: Confusing = with ==

# Wrong - assigns instead of compares
if x = 5 # This assigns 5 to x!

# Correct - compares values
if x == 5 # This compares x with 5

Mistake 2: Integer vs Float Division

# Surprising result
puts 10 / 3 # => 3 (not 3.33!)

# What you probably wanted
puts 10.0 / 3 # => 3.333...

Mistake 3: && vs and precedence

# Unexpected result
result = true and false # => true!

# What you probably wanted
result = true && false # => false

Learning Tips

Tip 1: Start with Simple Examples

Don't try to learn everything at once. Master basic arithmetic first, then move to comparison operators, and so on.

Tip 2: Use Parentheses for Clarity

Even when not required, parentheses make your code more readable and prevent precedence mistakes.

Tip 3: Practice with Real Data

Try using operators with actual data like user ages, prices, or scores to make learning more meaningful.

Tip 4: Experiment in IRB

Use Ruby's interactive shell (IRB) to test operators quickly without writing full programs.

Quick Navigation

Related Topics

Video Tutorial

Watch and learn ruby operators & operands

Pro Tip: After reading through the content above, watch this video to reinforce your understanding and see the concepts in action!