Blog / Compare
≠ ≤ ≥ vs !=, <= and >=
When to use which
| Character | When to use it | Watch out for |
|---|---|---|
| ≠ Not Equal To | Typeset mathematics, specifications, and any sentence a person reads: x ≠ y, or a constraint written ≠ 0. | Almost never in source code. Under NFD it splits into an equals sign plus a combining overlay, so a normalised copy of your text stops matching an un-normalised one. |
| ≤ Less-than Or Equal To Less Than Or Equal To | Ranges and bounds in prose, tables and data dictionaries: 0 ≤ x ≤ 1, a retention window of ≤ 30 days. | Two ASCII characters can break across a line between the angle and the bar; one character cannot. It is also East Asian Width Ambiguous, so a CJK terminal may hand it two cells. |
| ≥ Greater-than Or Equal To Greater Than Or Equal To | Thresholds and requirements, where >= reads as code in the middle of a sentence: ≥ 18, ≥ 2 GB. | The negated form ≱ decomposes back to this character plus a combining slash, so a search over NFD text starts matching the negation as well. |
All three of these signs are older than the keyboard in front of you, and the two-character operators that stand in for them — != for the first, <= and >= for the other two — exist because ASCII had ninety-five printable slots and was never going to spend one on a crossed-out equals sign. The direction of the substitution is the surprising part. ALGOL 60 defined its relational operators in the reference language as the real marks, ≠ and ≤ and ≥, and left each implementation to work out a hardware representation its printer could actually manage. C, a decade later, did the reverse: it wrote the operators in ASCII and never looked back, and because most languages since have been C-shaped, != is what a programmer means by "not equal" while ≠ is what a typesetter means.
The not-equal sign carries the one complication that follows the choice off the page and into your data. Unicode gives it a canonical decomposition — an equals sign followed by U+0338, the combining long solidus overlay — so under NFD and NFKD the single character comes apart into two, while NFC and NFKC leave it whole. Neither form is wrong; the trouble is holding both at once. Normalise on the way into a search index and not on the way in from a form, and a query for ≠ quietly matches nothing, in the way that has nothing to do with the query being wrong. Typing != has no such problem, because two ASCII characters are two ASCII characters under every normalisation there is. That is a genuine point in the operator's favour, and it is the only one on this list.
The case for less-than or equal to and greater-than or equal to is plainer, and it is about the line rather than the byte. Write <= in running text and you have written an angle bracket and an equals sign, two atoms a layout engine is entitled to separate when it justifies a line — so a tolerance can arrive with its bar orphaned at the start of the next one. The single characters cannot break, because there is nothing inside them to break. They also sit at the right optical weight for a sentence: ≥ 18 reads as a threshold, >= 18 reads as a fragment of code that fell into the paragraph. In a table of requirements or a data dictionary, that difference is most of the argument.
Markup adds a small tax of its own to the ASCII form. In XML, and in the HTML that inherits from it, a bare less-than sign in character data has to be escaped as <, so <= in a source document becomes <= before anything else happens to it — and a pipeline careless about the order of escaping and unescaping is where the mangled comparison operators in bug trackers come from. The named entities for the signs themselves are unambiguous by comparison: ≠, ≤ and ≥, with ≠ as a second name for the first.
Which languages let you have both
A handful never made the trade, which is the closest thing to a verdict available. APL did not give the signs up at all — ≠, ≤ and ≥ are its comparison functions, written exactly as a mathematician would write them, because the notation came before the keyboard built to type it. Julia accepts ≠, ≤ and ≥ as aliases for !=, <= and >=, so the same program can be written either way and the compiler cannot tell which you chose. Fortran went the other way and then partly back: it spelled the relations out as .NE., .LE. and .GE. through the 1977 standard, and Fortran 90 added /=, <= and >= alongside the older words. Pascal, BASIC and ML settled on <> for inequality, Lua and MATLAB on ~=, which is a useful reminder that != is a convention rather than a law.
So the split is not really mathematics against programming. It is whether the text will be parsed or read. A compiler needs an operator it can tokenise, and outside APL and Julia that means ASCII; a reader needs a sign shaped like the relation it names, and that means the character. Prose, specifications, tables, slides, anything typeset: use ≠, ≤ and ≥ — and reach for almost equal to or identical to when the relation you mean is genuinely one of those instead. Source code and anything a machine will tokenise: type the operator and let the compiler have its two characters. The option worth avoiding is the third one — writing != in a sentence because it was quicker to type — which mostly tells the reader you were in a terminal at the time.