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.