flowchart TD
OP["R Operators"] --> A["Arithmetic <br> + - * / ^ %% %/%"]
OP --> R["Relational <br> < <= > >= == !="]
OP --> L["Logical <br> & | ! && || xor"]
OP --> AS["Assignment <br> <- = ->"]
OP --> M["Miscellaneous <br> : %in% %*%"]
style OP fill:#e3f2fd,stroke:#1976D2
style A fill:#fff3e0,stroke:#F57C00
style R fill:#fff3e0,stroke:#F57C00
style L fill:#fff3e0,stroke:#F57C00
style AS fill:#f3e5f5,stroke:#8E24AA
style M fill:#e8f5e9,stroke:#388E3C
7 Types of Operators in R
This chapter is a tour of every operator R understands. You will learn the arithmetic operators (+, -, *, /, ^, %%, %/%), the relational operators (<, <=, >, >=, ==, !=), the logical operators (&, |, !, &&, ||, xor()), the assignment operators you already met (<-, =, ->), and the handful of miscellaneous operators that sit between them (:, %in%, %*%). You will also see how operator precedence and associativity decide the order of evaluation when an expression contains several operators, and how to override that order with parentheses. By the end of this chapter you will be able to read any arithmetic or logical expression in R and predict the result before you run it.
7.1 Arithmetic Operators
| Operator | Meaning | Example | Result |
|---|---|---|---|
+ |
Addition | 7 + 3 |
10 |
- |
Subtraction (also unary negation) | 7, 3, -4 |
4, -4 |
* |
Multiplication | 7 * 3 |
21 |
/ |
Division (always a double) | 7 / 3 |
2.333... |
^ |
Exponentiation | 2 ^ 10 |
1024 |
%% |
Modulus (remainder after integer division) | 7 %% 3 |
1 |
%/% |
Integer division (floor) | 7 %/% 3 |
2 |
Every arithmetic operator works element-by-element on vectors of the same length.
/ always returns a double, even when the inputs are whole numbers. %/% returns the integer part of the division, and %% returns the remainder. The identity a == (a %/% b) * b + (a %% b) holds for any non-zero b.
7.2 Relational Operators
| Operator | Meaning | Example | Result |
|---|---|---|---|
< |
Less than | 3 < 5 |
TRUE |
<= |
Less than or equal | 5 <= 5 |
TRUE |
> |
Greater than | 3 > 5 |
FALSE |
>= |
Greater than or equal | 5 >= 6 |
FALSE |
== |
Equal to | 3 == 3 |
TRUE |
!= |
Not equal to | 3 != 3 |
FALSE |
= When You Mean ==
A single = is assignment. A double == is equality. Writing if (x = 5) is a syntax error; writing if (x == 5) is the comparison you meant.
== Is Fragile
As Chapter 6 showed, floating-point values can look equal and not be. For comparing doubles, use all.equal() rather than ==.
7.3 Logical Operators
| Operator | Meaning | Vectorised? |
|---|---|---|
& |
Element-wise AND | Yes, element by element. |
| |
Element-wise OR | Yes, element by element. |
! |
NOT (negation) | Yes. |
&& |
Scalar AND (short-circuit, single value only) | No. |
|| |
Scalar OR (short-circuit, single value only) | No. |
xor(a, b) |
Exclusive OR | Yes. |
& vs && (and | vs ||)
The single-symbol forms (&, |) work element-by-element and are the right choice for filtering vectors. The double-symbol forms (&&, ||) expect one value on each side and “short-circuit”, they stop evaluating as soon as the answer is known. Starting from R 4.3, using && or || with longer vectors emits a warning.
&& and || Inside if, & and | Inside ifelse() or Filtering
When writing a single-branch if statement you want one answer, so use && or ||. When filtering a vector or using ifelse(), you want a vector of answers, so use & or |.
7.4 Assignment Operators
You met <-, =, and -> in Chapter 4. They are listed here for completeness and because they are operators in the formal sense.
| Operator | Direction | Typical Use |
|---|---|---|
<- |
Right to left | The idiomatic choice for assignment. |
= |
Right to left | Assignment; also used for named function arguments. |
-> |
Left to right | Legal but rare; sometimes useful at the end of a pipeline. |
7.5 Miscellaneous Operators
| Operator | Meaning | Example |
|---|---|---|
: |
Generate an integer sequence from a to b. |
1:5 → 1 2 3 4 5 |
%in% |
Test membership: is the left value in the right vector? | 3 %in% c(1,3,5) → TRUE |
%*% |
Matrix multiplication (used in Module 2). | A %*% B |
%in% Is Almost Always What You Want
Beginners sometimes write day == "Sat" | day == "Sun". For one comparison that is fine; for five it is noisy. day %in% c("Sat", "Sun") says exactly the same thing with less clutter and scales to any list of allowed values.
Any function whose name is surrounded by %...% behaves as a binary operator. This is how %in% and %*% themselves are defined, and it is how the magrittr pipe %>% works.
7.6 Operator Precedence and Parentheses
When an expression contains more than one operator, R uses a fixed precedence to decide the order. Higher precedence operators are evaluated first. The table below is not exhaustive, but it covers every operator you have met so far, from highest precedence at the top to lowest at the bottom.
| Priority | Operators |
|---|---|
| 1 (highest) | ::, $, @, [, [[ |
| 2 | ^ (right-to-left) |
| 3 | Unary +, unary - |
| 4 | : |
| 5 | %%, %/%, %in%, %*%, any %any% |
| 6 | *, / |
| 7 | +, - |
| 8 | <, <=, >, >=, ==, != |
| 9 | ! |
| 10 | &, && |
| 11 | |, || |
| 12 | <-, =, -> (lowest) |
The precedence table exists, but no one reading your code wants to consult it. If an expression depends on non-obvious precedence, wrap the sub-expression in parentheses. It costs two characters and buys lasting readability.
7.7 A Worked Example: Filtering Students
The snippet below combines arithmetic, relational, logical, and membership operators to answer a simple question: which students passed with distinction, and what is their average?
Notice the sequence: relational operators produce logical vectors, & combines them element-wise, %in% replaces a chain of ==, and logical indexing pulls out the matching names at the end.
7.8 Summary
| Concept | Key Takeaway |
|---|---|
| Arithmetic operators | +, * / ^ %% %/%; all of them vectorise. |
| Relational operators | < <= > >= == !=; they return logical vectors. |
| Logical operators | & | ! for element-wise, && || for single values. |
| Assignment operators | <- idiomatic, = for named arguments, -> rare. |
| Miscellaneous | : for sequences, %in% for membership, %*% for matrix multiplication. |
| Precedence | ^ before * / / before + / -; comparison before & / |; assignment last. |
| Parentheses | When in doubt, add them, they cost two characters and explain the intent. |
Doubles and == |
Use all.equal() instead of == for floating-point equality. |
Operators are the punctuation of R. Fluent readers know the precedence rules well enough to trust them and reach for parentheses when the expression gets even slightly non-trivial. In the next chapter you will step back and look at R’s data structures as a family, so you can match each operator to the kind of object it naturally works on.