# Ordering problem

Let's look at the following example.

Ordering[{0, 20 Sqrt, 40 Sqrt, 20 Sqrt, 20 Sqrt} // N]


{1, 2, 4, 5, 3}


but if one removes the N, one gets the wrong answer

Ordering[{0, 20 Sqrt, 40 Sqrt, 20 Sqrt, 20 Sqrt}]

{1, 2, 4, 3, 5}


Is it a bug?

• For a similarly confusing problem with the same origin, look here Mar 8 '12 at 16:38

This is probably because by default Sort doesn't just use numerical values, it includes structure information as well. From the doc:

Numeric expressions are sorted by structure as well as numerical value:

In:= Sort[{Sqrt, 1, 2, 1/Sqrt}]

Out= {1, 2, 1/Sqrt, Sqrt}


Sort by numerical value only:

In:= Sort[{Sqrt, 1, 2, 1/Sqrt}, Less]

Out= {1/Sqrt, 1, Sqrt, 2}


along with the following doc:

Sort usually orders expressions by putting shorter ones first, and then comparing parts in a depth-first manner.

gives us a hint why. If you run TreeForm /@ {0, 20 Sqrt, 40 Sqrt, 20 Sqrt, 20 Sqrt}, you'll see that the last layer (Rational) is the same for all four Sqrts. Then the next depth down is the Power, in which 10 is the outlier, and is greater than 5, so will be placed last. Finally, comparing {20, 40, 20} will give the ordering {1, 3, 2}, which when put together with the original list gives you the ordering:

In:= Ordering[{0, 20 Sqrt, 40 Sqrt, 20 Sqrt, 20 Sqrt}]

Out= {1, 2, 4, 3, 5}

• nice explanation.. Mar 8 '12 at 15:56
• Thanks! I actually learned a bit about MMA's sorting :). Good question! Mar 8 '12 at 15:56
• +1, one more thing I have to check when I'm using it, like the non-orthogonality of Eigenvectors with the same eigenvalue ... :| Mar 8 '12 at 16:01

No, this is not a bug, and Ordering does not give a wrong answer.

Quoting the documentation of Sort,

Sort[list,p] applies the function p to pairs of elements in list to determine whether they are in order. The default function p is OrderedQ[{#1, #2}] &.

As you can see, Sort (and Ordering) compares using OrderedQ, not Less.

OrderedQ uses a special ordering that is applicable to any Mathematica expressions, not just numbers. Read about it on the doc page of Sort.

The rule I believe applies here is the following:

Sort treats powers and products specially, ordering them to correspond to terms in a polynomial.

This means that terms are interpreted as if they were in the form 10 var1 + 20 var2, i.e. variables with coefficients. The ordering is determined by the ordering of "variables" (which in your example correspond to Sqrt and Sqrt), and not their coefficients. Thus the canonical ordering is {40 Sqrt, 20 Sqrt} and not the reverse, because Sqrt comes before Sqrt in the canonical order.

The reason for doing this is that Orderless functions will auto-sort their arguments in the same way. Thus if you write a polynomial, 10 y + 20 x, it'll be ordered on the variables yielding 20 x + 10 y.

So, if you want numerical expressions sorted by numerical magnitude, use

SortBy[list, N]


If you want to get the permutation that sorts them, use

Ordering[ N[list] ]

• I am certain that this has been asked either here or on SO, but I couldn't find it. Mar 8 '12 at 16:01
• I agree, it has been. I know it came up in reference to displaying Orderless functions. However, that is the only place that comes to mind off the top of my head. Mar 8 '12 at 16:14
• @rcollyer It is another question I remembered. It was also about why Sort doesn't sort by numerical value. I wanted to link to it, but I couldn't find it. Regarding the question you linked to, PolynomialForm[1 + x, TraditionalOrder -> True] is interesting. Just like TraditionalForm, it changes the printing order of polynomials. Mar 8 '12 at 16:19
• PolynomialForm appears to be undocumented. Although, ?System*Form does make for interesting reading. Mar 8 '12 at 16:23

# NumericalSort

This behavior of Sort is indeed the documented behavior. However I also find it not intuitive.

There is a function called NumericalSort (as of Mathematica 11.1) which sorts the elements of a list by numerical order. It uses NumericalOrder as the ordering function i.e. Sort[list, NumericalOrder].

# Examples

(* different results *)

Sort[{1, -Pi}] -> {1, -Pi}
NumericalSort[{1, -Pi}] -> {-Pi, 1}

Sort[{{1, 2}, {-Pi, 2}}] -> {{1, 2}, {-Pi, 2}}
NumericalSort[{{1, 2}, {-Pi, 2}}] -> {{-Pi, 2}, {1, 2}}

Sort[{{"b", 2}, {Pi, 1}}] -> {{"b", 2}, {Pi, 1}}
NumericalSort[{{"b", 2}, {Pi, 1}}] -> {{Pi, 1}, {"b", 2}}

(* same results *)

Sort[{{"b", 2}, {"a", 1}}] -> {{"a", 1}, {"b", 2}}
NumericalSort[{{"b", 2}, {"a", 1}}] -> {{"a", 1}, {"b", 2}}
`