Relational operator
In computer science, a relational operator is a programming language construct or operator that tests or defines some kind of relation between two entities. These include numerical equality and inequalities.
In programming languages that include a distinct boolean data type in their type system, like Pascal, Ada, or Java, these operators usually evaluate to true or false, depending on if the conditional relationship between the two operands holds or not. In languages such as C, relational operators return the integers 0 or 1, where 0 stands for false and any non-zero value stands for true.
An expression created using a relational operator forms what is termed a relational expression or a condition. Relational operators can be seen as special cases of logical predicates.
Equality
Usage
Equality is used in many programming language constructs and data types. It is used to test if an element already exists in a set, or to access to a value through a key. It is used in switch statements to dispatch the control flow to the correct branch, and during the unification process in logic programming.One possible meaning of equality is that "if a equals b, then either a or b can be used interchangeably in any context without noticing any difference." But this statement does not necessarily hold, particularly when taking into account mutability together with content equality.
Sameness (object identity) vs. content equality
Sometimes, particularly in object-oriented programming, the comparison raises questions of data types and inheritance, equality, and identity. It is often necessary to distinguish between:- two different objects of the same type, e.g., two hands
- two objects being equal but distinct, e.g., two $10 banknotes
- two objects being equal but having different representation, e.g., a $1 bill and a $1 coin
- two different references to the same object, e.g., two nicknames for the same person
- Physical equality: if two references reference the same object. Interactions with the object through A are indistinguishable from the same interactions through B, and in particular changes to the object through A are reflected through B. Physical identity is not applicable when talking about values instead of objects.
- Semantic equality: if the objects referenced by two references, or if two values, are equivalent in some sense:
Real numbers, including many simple fractions, cannot be represented exactly in floating-point arithmetic, and it may be necessary to test for equality within a given tolerance. Such tolerance, however, can easily break desired properties such as transitivity, whereas reflexivity breaks too: the IEEE floating point standard requires that NaN ≠ NaN holds.
Other programming elements such as computable functions, may either have no sense of equality, or an equality that is uncomputable. For these reasons, some languages define an explicit notion of "comparable", in the form of a base class, an interface, a trait or a protocol, which is used either explicitly, by declaration in source code, or implicitly, via the structure of the type involved.
Comparing values of different types
In JavaScript, PHP, VBScript and a few other dynamically typed languages, the standard equality operator evaluates to true if two values are equal, even if they have different types, making the number 4 compare equal to the text string "4", for instance. A typed equality operator is often available also, in such languages, returning true only for values with identical or equivalent types. For languages where the number 0 may be interpreted as false, this operator may simplify things such as checking for zero.Ordering
Greater than and less than comparison of non-numeric data is performed according to a sort convention which may be built into the programming language and/or configurable by a programmer.When it is desired to associate a numeric value with the result of a comparison between two data items, say a and b, the usual convention is to assign −1 if a < b, 0 if a = b and 1 if a > b. For example, the C function
strcmp
performs a three-way comparison and returns −1, 0, or 1 according to this convention, and qsort expects the comparison function to return values according to this convention. In sorting algorithms, the efficiency of comparison code is critical since it is one of the major factors contributing to sorting performance.Comparison of programmer-defined data types may be carried out by custom-written or library functions, or, in some languages, by overloading a comparison operator – that is, assigning a programmer-defined meaning that depends on the data types being compared. Another alternative is using some convention such as memberwise comparison.
Logical equivalence
Though perhaps unobvious at first, like the boolean logical operators XOR, AND, OR, and NOT, relational operators can be designed to have logical equivalence, such that they can all be defined in terms of one another. The following four conditional statements all have the same logical equivalence E for any given x and y values:This relies on the domain being well ordered.
Standard relational operators
The most common numerical relational operators used in programming languages are shown below.Convention | equal to | not equal to | greater than | less than | greater than or equal to | less than or equal to |
In print | = | ≠ | > | < | ≥ | ≤ |
FORTRAN | .EQ. | .NE. | .GT. | .LT. | .GE. | .LE. |
ALGOL 68 | = | ≠ | > | < | ≥ | ≤ |
ALGOL 68 | = | /= | > | < | >= | <= |
ALGOL 68 | eq | ne | gt | lt | ge | le |
APL | = | ≠ | > | < | ≥ | ≤ |
BASIC, ML, Pascal | = | <> | > | < | >= | <= |
MUMPS | = | '= | > | < | '< | '> |
Lua |
| ~= | > | < | >= | <= |
C-like |
| != | > | < | >= | <= |
Erlang |
| != | > | < | >= | =< |
Erlang | =:= | =/= | > | < | >= | =< |
Bourne-like shells | -eq | -ne | -gt | -lt | -ge | -le |
Batch file | EQU | NEQ | GTR | LSS | GEQ | LEQ |
MATLAB |
| ~= | > | < | >= | <= |
MATLAB | eq | ne | gt | lt | ge | le |
Fortran 90, Haskell |
| /= | > | < | >= | <= |
Mathematica |
| != | > | < | >= | <= |
Mathematica | Equal | Unequal | Greater | Less | GreaterEqual | LessEqual |
Other conventions are less common: Common Lisp and Macsyma/Maxima use Basic-like operators except for inequality, which is
/=
in Common Lisp and #
in Macsyma/Maxima. Older Lisps used equal
, greaterp
, and lessp
; and negated them using not
for the remaining operators.Syntax
Relational operators are also used in technical literature instead of words. Relational operators are usually written in infix notation, if supported by the programming language, which means that they appear between their operands. For example, an expression in Python will print the message if the x is less than y:if x < y:
Other programming languages, such as Lisp, use prefix notation, as follows:
Operator chaining
In mathematics, it is common practice to chain relational operators, such as in 3 < x < y < 20. The syntax is clear since these relational operators in mathematics are transitive.However, many recent programming languages would see an expression like 3 < x < y as consisting of two left associative operators, interpreting it as something like
< y
. If we say that x=4, we then get < y
, and evaluation will give true < y
which generally does not make sense. However, it does compile in C/C++ and some other languages, yielding surprising result.It is possible to give the expression
x < y < z
its familiar mathematical meaning, and some programming languages such as Python and Raku do that. Others, such as C# and Java, do not, partly because it would differ from the way most other infix operators work in C-like languages. The D programming language does not do that since it maintains some compatibility with C, and "Allowing C expressions but with subtly different semantics would add more confusion than convenience".Some languages, like Common Lisp, use multiple argument predicates for this. In Lisp
is true when x is between 1 and 10.Confusion with assignment operators
Early FORTRAN was bounded by heavily restricted character sets where=
was the only relational operator available. There were no <
or >
. This forced the designers to define symbols such as .GT.
, .LT.
, .GE.
, .EQ.
etc. and subsequently made it tempting to use the remaining =
character for copying, despite the obvious incoherence with mathematical usage.International Algebraic Language and ALGOL thus introduced
:=
for assignment, leaving the standard =
available for equality, a convention followed by CPL, ALGOL W, ALGOL 68, Basic Combined Programming Language, Simula, SET Language, Pascal, Smalltalk, Modula-2, Ada, Standard ML, OCaml, Eiffel, Object Pascal, Oberon, Dylan, VHSIC Hardware Description Language, and several other languages.B and C
This uniform de facto standard among most programming languages was eventually changed, indirectly, by a minimalist compiled language named B. Its sole intended application was as a vehicle for a first port of Unix, but it also evolved into the very influential C language.B started off as a syntactically changed variant of the systems programming language BCPL, a simplified version of CPL. In what has been described as a "strip-down" process, the
and
and or
operators of BCPL were replaced with &
and |
. In the same process, the ALGOL style :=
of BCPL was replaced by =
in B. The reason for all this being unknown. As variable updates had no special syntax in B and were allowed in expressions, this non standard meaning of the equal sign meant that the traditional semantics of the equal sign now had to be associated with another symbol. Ken Thompson used the ad hoc
combination for this.As a small type system was later introduced, B then became C. The popularity of this language along with its association with Unix, led to Java, C#, and many other languages following suit, syntactically, despite this needless conflict with the mathematical meaning of the equal sign.
Languages
Assignments in C have a value and since any non-zero scalar value is interpreted as true in conditional expressions, the codeif
is legal, but has a very different meaning from if
. The former code fragment means "assign y to x, and if the new value of x is not zero, execute the following statement". The latter fragment means "if and only if x is equal to y, execute the following statement".int x = 1;
int y = 2;
if
Though Java and C# have the same operators as C, this mistake usually causes a compile error in these languages instead, because the if-condition must be of type
boolean
, and there is no implicit way to convert from other types into boolean
s. So unless the variable that is assigned to has type boolean
, there will be a compile error.In ALGOL-like languages such as Pascal, Delphi, and Ada, and in Python, and many functional languages, among others, assignment operators cannot appear in an expression, thus precluding this class of error. Some compilers, such as GNU Compiler Collection, provide a warning when compiling code containing an assignment operator inside an if statement, though there are some legitimate uses of an assignment inside an if-condition. In such cases, the assignment must be wrapped in an extra pair of parentheses explicitly, to avoid the warning.
Similarly, some languages, such as BASIC use just the
=
symbol for both assignment and equality, as they are syntactically separate.Some programmers get in the habit of writing comparisons against a constant in the reverse of the usual order:
if
If
=
is used accidentally, the resulting code is invalid because 2 is not a variable. The compiler will generate an error message, on which the proper operator can be substituted. This coding style is termed left-hand comparison, or Yoda conditions.This table lists the different mechanisms to test for these two types of equality in various languages:
Language | Physical equality | Structural equality | Notes |
ALGOL 68 | a :=: b or a is b | a = b | when a and b are pointers |
C, C++ | a b | *a *b | when a and b are pointers |
C# | object.ReferenceEquals | a.Equals | The operator defaults to ReferenceEquals , but can be overloaded to perform Equals instead. |
Common Lisp |
|
| |
Erlang | a =:= b | a b | when a and b are numbers |
Go | a b | reflect.DeepEqual | when a and b are pointers |
Java | a b | a.equals | |
JavaScript | a b | a b | when a and b are two string objects containing equivalent characters, the operator will still return true. |
OCaml, Smalltalk | a b | a = b | |
Pascal | a^ = b^ | a = b | |
Perl | $a $b | $$a $$b | when $a and $b are references to scalars |
PHP5 | $a $b | $a $b | when $a and $b are objects |
Python | a is b | a b | |
Ruby | a.equal? | a b | |
Scheme |
|
| |
Swift | a b | a b | when a and b have class type |
Visual Basic.NET | a Is b or object.ReferenceEquals | a = b or a.Equals | Same as C# |
Objective-C | a b |
| when a and b are pointers to objects that are instances of NSObject |
Ruby uses
a b
to mean "b is a member of the set a", though the details of what it means to be a member vary considerably depending on the data types involved.
is here known as the "case equality" or "case subsumption" operator.