natsort() pain in PHP

While writing some software for work which works out distances between geographic locations, I discovered some nastiness with the natsort() function in php.

This function implements a sort algorithm that orders alphanumeric strings in the way a human being would while maintaining key/value associations. This is described as a “natural ordering”.

So, given this definition of natsort, I’ll now outline a working example and then an example of the problem I encountered.
Lets say we have a list of values in an array that need to be sorted descending whilst maintaining key/value pairs. E.g:

$a = array(4 => 9.1, 3 => 4.2, 10 => 4.5);
natsort($a);

As you would expect, the resulting array looks a little something like this.

print_r($a);
Array
(
[3] => 4.2
[10] => 4.5
[4] => 9.1
)

But what happens when the values in the array we are trying to sort are a little more complex:

$a = array(4 => 9.11705244995,3 => 4.23956628237,10 => 4.5361796771);
natsort($a);

The resulting array isn’t what we expect though.

print_r($a);
Array
(
[10] => 4.5361796771
[3] => 4.23956628237
[4] => 9.11705244995
)

As you can see, the sort order is incorrect. As you have probably picked up, the 4.5xxx number’s decimal places are 1 less than the other two numbers. As soon as you change 4.5361796771 to 4.53617967711 and run natsort() over it, it returns the correct order.

Conclusion: Don’t use natsort() when sorting floats of different precision as it will return incorrect values! Use something like asort() if you want to maintain key/value pairs, or sort() if you don’t care about the key ordering.