Numeric comparison operators#

Seven operators that compare two numbers and return either a boolean (the first six) or a three-way result (<=>).

Operator

Question

Returns

<

less than

true / false

<=

less or equal

true / false

==

equal

true / false

>=

greater or equal

true / false

>

greater than

true / false

!=

not equal

true / false

<=>

three-way (sort)

-1, 0, or +1

All seven coerce both operands to numbers before comparing.

$age   >= 18                  # true if 18 or older
$count == 0                   # true if numerically zero
$x     != $y                  # true if they differ numerically
$a    <=>  $b                 # -1 if $a < $b, 0 if equal, +1 if $a > $b

== is for numbers, eq is for strings#

This is the single most common bug new Perl programmers ship. == compares numerically — both operands are run through numeric coercion, and any non-numeric string becomes 0:

"foo" == "bar"        # TRUE  -- both coerce to 0
"42x" == "42y"        # TRUE  -- both coerce to 42
"1e2" == 100          # TRUE  -- "1e2" is 100 in scientific notation

For string equality, use eq:

"foo" eq "bar"        # FALSE  -- the actual question
"42x" eq "42y"        # FALSE

If use warnings is in scope, the Argument "..." isn't numeric warning fires every time == (or any other numeric operator) sees a non-numeric string. That warning is your friend.

<=> — the spaceship operator#

<=> returns -1 if the left is smaller, 0 if equal, +1 if greater. It is the sort comparator:

my @sorted = sort { $a <=> $b } @numbers;       # ascending
my @rev    = sort { $b <=> $a } @numbers;       # descending

# multi-key: by length, ties broken by content
my @lines = sort { length($a) <=> length($b) || $a cmp $b } @raw;

The pattern cmp1 || cmp2 || cmp3 works because <=> returns 0 on ties and || falls through on 0. See logical.

<=> and cmp are the only two operators on this family that are not boolean — they are integer-valued and exist for sorting, not for if-conditions.

Floating-point equality#

== on floats is exact bit-for-bit equality. For values produced by floating-point arithmetic this is almost never what you want:

0.1 + 0.2 == 0.3      # FALSE  -- 0.30000000000000004

Compare with a tolerance:

abs($a - $b) < 1e-9              # absolute tolerance
abs($a - $b) < 1e-9 * abs($a)    # relative tolerance, when $a ≠ 0

abs is a named-unary operator.

Chaining is not magic#

Perl does not support mathematical chaining of comparisons. $a < $b < $c does not test «$b is between $a and $c» — it parses as ($a < $b) < $c, where the first comparison yields a boolean ("" or 1) which is then numerically compared with $c:

1 < 5 < 3        # parses as (1 < 5) < 3
                 #         = 1 < 3
                 #         = TRUE   -- which is *not* what you meant.

Write the conjunction explicitly:

$a < $b && $b < $c     # the actual "between" test

Precedence#

Comparison operators sit at row 11 of the precedence table — looser than the arithmetic operators (so $a + $b == $c + $d works), tighter than the logical operators (so $a < $b && $c > $d works). They are non-associative: $a < $b < $c is not invalid, but the non-associativity warning explained above applies.

See also#