# Implement the <=> three-way comparison operator on numbers

In C++, there exists a a <=> b three-way comparison operator that, for numerical types, does the following:

• If a < b, then return a negative number.
• If a = b, then return a (mathematically speaking) sign-less number.
• If a > b, then return a positive number.

## The Challenge

Implement the shortest full program, function, method, or custom operator such that, when given two numbers of the same type a and b,

• If a < b, then return -1.
• If a = b, then return 0.
• If a > b, then return 1.

### Notes

• If you're writing in x86 assembly, this question may be of use to you.
• This is , so shortest answer in bytes wins!
• Do we have to handle all combinations of inputs? (I.e. can we assume that a - b will yield the arithmetic result, even when a is the lowest representable value and b is the highest?) Commented Mar 20, 2023 at 13:15
• @TobySpeight You will need to handle all combinations of inputs. Commented Mar 20, 2023 at 13:22
• Note that the C++ 3-way comparison is actually "compares equal to 0" and "compares less than 0" and "compares greater than 0". 1 and -1 are explicitly not required, by design, unlike your ask. I only mention this because your first paragraphs are not true.
– Yakk
Commented Mar 21, 2023 at 14:57
• If a language has support for multiple numeric types, such as integers and floating point numbers, does it need to support all of them? Basically every solution using subtraction and supporting floating point numbers doesn't work. Commented Mar 22, 2023 at 9:47
• @Tyilo the original draft of this challenge in sandbox had a bonus for supporting multiple numeric types, but was cut because "bonuses are bad". Pick whichever numeric type leads to the shortest solution. Commented Mar 22, 2023 at 13:04

# AArch64 machine code, 16 bytes

AArch64's conditional select instructions get their time to shine.

0000000000000000 <spaceship>:
0:   eb01001f    cmp x0, x1
4:   9a9f07e0    cset x0, ne
8:   da80a400    cneg x0, x0, lt
c:   d65f03c0    ret


cset sets the destination register to 1 or 0 according to whether the condition code is true or false. (Fun fact: it's actually an alias for csinc x0, xzr, xzr, eq, where csinc X, Y, Z, cond sets X to Y if the condition is true, and to Z+1 if false.)

cneg X, Y, cond sets X either to -Y or Y according to whether the condition is true or false. (Alias for csneg X, Y, Y, cond.)

Several other permutations are also possible, such as

cset x0, gt              // x0 = (a > b) ? 1 : 0
csinv x0, x0, xzr, lt    // x0 = (a < b) ? x0 : ~0


a#b|a<b= -1|a>b=1|0<1=0


Try it online!

-1, thanks to Unrelated String!

The 'nicer' solution of ((pred.fromEnum).).compare is 26 bytes.

• True -> 0<1 for -1 Commented Mar 23, 2023 at 1:40

# Lua, 45 bytes

load"a,b=...return a>b and 1or a<b and-1or 0"


Try it online!

Lua has a strict type system, and there is no shorter way than a and 1or 0 to convert a boolean to an integer.

This version works for all comparable types (e.g. integer, floating point, and string).

# Lua, 35 bytes

load"a,b=...return-1+2/(0^(a-b)+1)"


Try it online!

This is based on my answer to Output the sign. It gives the correct result for all floating point inputs, and most integer inputs.

It doesn't meet the requirements of this challenge for integer inputs, as it will fail when passed, for example, math.maxinteger and math.mininteger (as demonstrated in the test harness), because subtracting one from the other results in an overflow. But it does fully work for all floating point inputs, thus meeting the challenge's requirements for that type.

• You can save six bytes by taking in program arguments and printing out the answer instead of using the load function like this Commented Apr 10, 2023 at 11:37
• @bluswimmer Thanks, but I chose a function because it's a more elegant form of presentation, takes its input in an actual type instead of as strings, and can easily process more than one input in the test harness. I don't know if it's even possible to make a TIO or ATO test harness in Lua that demonstrates more than one input with a full program. So you could consider my choice of language is "Lua function", which means that a full program wouldn't beat it, since it wouldn't be in the same language. Commented Apr 10, 2023 at 16:43
• @bluswimmer Case in point: The TIO you gave me is comparing the input as strings, not numbers. Without yet having tried it yet, I'm guessing a full program to compare numbers will actually be longer due to the need to convert the strings to numbers. Commented Apr 10, 2023 at 16:49

# Wolfram Language (Mathematica), 5 bytes

Order


Try it online!

Input Order[b, a]. Works on any atomic numbers.

Note the reversed order of inputs.

# PowerShell, 19 bytes

[math]::Sign($a-$b)


Try it online!

# minigolf, 18 bytes

TiiT*+1+,:1+s,T+__


Attempt This Online! (Since minigolf is not properly added to ATO yet, I'm using a Python runner here.)

## Explanation

We use -1 as the base of our output. If a-b >= 0, we increment -1 a-b+1 times. However, if our output reaches 2, we decrement it back to 1.

T                 0, Base our signum output on -1 _
iiT*+             0, a + b * -1 _
1+                0, increment the result _
,                 0, Repeat that many times: _
:1+s            0, Increment signum but keep the original value _
0, This is useful because we only want to _
0, decrement once in the 2 case _
,               0, If our previous signum value is 1: do this once _
T+            0, Add signum value by -1 _
_               0, End foreach loop _
_                 0, End foreach loop _

0, Implicit output the signum value left on the stack _
$$$$

• Welcome to Code Golf, and nice answer/language! Commented Apr 15, 2023 at 3:13

# Jelly, 2 bytes

_Ṡ


A dyadic Link that accepts $$\a\$$ on the left and $$\b\$$ on the right and yields $$\a \lt = \gt b\$$.

Try it online!

### How?

_Ṡ - Link: a, b
_  - (a) subtract (b)
Ṡ - sign -> -1, 0, or 1


# ARBLE, 25 15 bytes

lt(a,b)-gt(a,b)


Same as Arnauld's JS solution. Unfortunately Verbose, throwing away the advantages of the langauge.

Try it online!

# Japt, 2 bytes

gV


Try it

g   # sign of the difference of implicit first input and
V  # second input

• What does V do, then? Commented Mar 20, 2023 at 1:55
• @Seggan This program transpiles to the JS U.g(V), where U is the first input and V is the second Commented Mar 20, 2023 at 1:56

# Thunno, $$\ 3\log_{256}(96)\approx\$$ 2.47 bytes

_za


Attempt This Online!

Sign of a-b.

# Brachylog, 2 bytes

-ṡ


Try it online!

Same answer as many other esolangs.

### Explanation

-     Subtract
ṡ    Sign


# Ruby, 12 bytes

->a,b{a<=>b}


Try it online!

(feels like cheating)

• I suggest adding this to the CW for languages with the exact <=> operator. Commented Mar 20, 2023 at 15:53
• ->{_1<=>_2} is one byte shorter. Commented Mar 21, 2023 at 1:17
• @south ->{_1<=>_2} doesn't seem to work when copy-pasted into TIO... Commented Mar 21, 2023 at 9:05
• TIO uses an out-of-date ruby version. Implicit block parameters were added after 2.5.5. Commented Mar 21, 2023 at 20:35
• proc &:<=> is 10 bytes. Commented Mar 22, 2023 at 3:54

# simply, 8 bytes

Does exactly the expected.

&compare


This is a built-in function that simply returns the expected result.

## Example:

### Code-like

// Should output 1
echo &compare(2, 1);


### Plain-English-like

// Should output -1
Show the result of calling &compare with the arguments 1, 2.


## Test code:

This shows test results in a nice pretty table.

// Test data - self-explanatory
// Example 5 shows an error, as an example
$tests = &json_decode(<<<JSON [ {"a": 0, "b": 1, "result": -1}, {"a": 1, "b": 2, "result": -1}, {"a": 2, "b": 1, "result": 1}, {"a": 2, "b": 2, "result": 0}, {"a": 3, "b": 2, "result": 0} ] JSON); // Make the table pretty$settings = call !TABLE->getDefaultSettings();
$settings->classHeader = &str_concat($settings->classHeader, " table-dark");
$settings->classBodyCell = &str_concat($settings->classBodyCell,
" text-center"
);
$settings->classBodyFirstCol = &str_concat($settings->classBodyFirstCol,
" text-center table-dark"
);
$settings->classHeaderItems = &str_concat($settings->classHeaderItems,
" w-25"
);

// Create the table
$table = call !TABLE->create($settings);

call $table->setHeader(["", "A", "B", "Result"]); each$test in $tests { // This is where the function runs$result = &compare($test['a'],$test['b']);

call $table->addRow( &iff($result == $test["result"], "✔️", &str_concat("❌ (",$test["result"], ")")
),
$test['a'],$test['b'],
$result ); } call$table->show();


### Result:

This is an example of how the table will look like.

# Desmos, 15 bytes

f(a,b)=sgn(a-b)


Try It On Desmos!

# Binary-encoded Golfical, 27 bytes

Hexdump of binary encoding:

00 30 07 15 14 14 14 14 17 17 0c 01 14 14 14 17
00 01 02 01 1c 15 3b 4e 23 26 1d


Original program image:

Magnified 40x with RGB colors labeled:

# Common Lisp, 28 bytes

(lambda(a b)(signum(- a b)))


# MMIX machine language, 2 instrs (8 bytes)

For s64:

00000000: 30000001 f8010000                    0¡¡¢ẏ¢¡¡


Disassembled:

    CMP $0,$0,$1 // x = x <=> y POP 1,0 // return x  For u64: 00000000: 32000001 f8010000 2¡¡¢ẏ¢¡¡  Disassembled, the only change is the first instruction is now CMPU. For f64: 00000000: 01000001 f8010000 ¢¡¡¢ẏ¢¡¡  And this time the first instruction is FCMP. All of these functions are excellent candidates for inlining. # Ly, 14 bytes nns=!rlLfp2*,*  Try it online! Longer than I'd hoped, but I couldn't find a shorter way to do it given the instructions available... nns - read in two numbers, stash the second one away =! - are they equal? invert result so "0" is set for equal rl - reverse stack, recover the second number L - do "less than" comparison fp - delete the first number (it's still on the stack) 2*, - converts "0" to "-1" and "1" stays "1" * - multiple by "are they equal?" val to get "0" as needed  # Python, 31 Bytes lambda a,b:(x:=a-b)and x/abs(x)  -7 Bytes from The Thonnu. abs(x) gets the absolute value of x (think of it as scissors that can cut the - sign off numbers). • I would recommend using either Try it online! or Attempt This Online! before submitting an answer. It allows you and others to test your program, and you can also copy the submission from there instead of writing it up yourself. Commented Apr 6, 2023 at 13:18 • Also, 32 bytes, or 31 bytes in Python 3.8+ Commented Apr 6, 2023 at 13:21 # PARI/GP, 3 bytes cmp  Attempt This Online! ## Common Lisp, 24 bytes (compose'floor'signum'-)  This is the functional composition of functions floor, signum and -. The signum function computes the sign and return the expected values, but for floating point values the result is also a float, either -1.0, -0.0, +0.0 or +1.0. That's why the floor operation is used to convert the result back to an integer. # Gaia, 1 byte C  Try it online! # Thunno 2, 1 byte ṛ  Attempt This Online! Built-in. Inputs in reverse order, b then a. Requires $$\\le 2.2.0\$$, as this was changed in Thunno $$\2.2.1\$$. ## Thunno 2, 2 bytes _ʂ  Same as most other answers: sign of a-b. Inputs in normal order, a then b. Works in all versions. Attempt This Online! # Arturo, 7 bytes compare  Try it Builtin. (In Arturo, <=> is the between operator. 5 <=> 1 10 would return true.) # Arturo, 33 bytes $[a b][(a>b)?->1->(a=b)?->0->0-1]


Try it

Non-builtin.

Arturo doesn't have a sign function or integer booleans, so I couldn't think of anything better than a nested ternary.

# Factor, 9 bytes

[ - sgn ]


Try it online!

Sign of difference. Factor has a <=> word, but it returns +lt+, +eq+, and +gt+ symbols.

# Desmoslang Assembly, 5 Bytes

I-IOT


I belive you had said that any negative or positive number works.

# YASEPL, 40 bytes

=x=a'=b'!a}1,b,3}3,b}2,b,23!\$|2!-|1>x


takes 2 inputs from STDIN.