# 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. ```perl $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`: ```perl "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`](string-comparison.md): ```perl "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: ```perl 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](logical.md). `<=>` and [`cmp`](string-comparison.md) 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: ```perl 0.1 + 0.2 == 0.3 # FALSE -- 0.30000000000000004 ``` Compare with a tolerance: ```perl abs($a - $b) < 1e-9 # absolute tolerance abs($a - $b) < 1e-9 * abs($a) # relative tolerance, when $a ≠ 0 ``` [`abs`](../perlfunc/abs.md) is a [named-unary](precedence.md) 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`: ```perl 1 < 5 < 3 # parses as (1 < 5) < 3 # = 1 < 3 # = TRUE -- which is *not* what you meant. ``` Write the conjunction explicitly: ```perl $a < $b && $b < $c # the actual "between" test ``` ## Precedence Comparison operators sit at row 11 of the [precedence](precedence.md) 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 - [String comparison](string-comparison.md) — `eq ne lt le gt ge cmp`, the lexical-order family. - [Logical operators](logical.md) — combining comparison results. - [`<=>` in sort](../perlfunc/sort.md) — the canonical use case. - [Boolean Logic for Perl Programmers](../../../tutorial/boolean-logic/truthiness.md) — the ”two flavours of comparison“ overview that motivates the numeric/string split. - [Numbers and strings](../perldata/numeric-strings.md) — when a scalar gets coerced to a number, and the precision/Inf/NaN story behind `==`.