Wise Words

In fear of this website disappearing, I would like to re-blog the words to which I can relate to on a daily basis. Original text can (hopefully) be found here.


"You know, when you have a program that does something really
cool, and you wrote it from scratch, and it took a
significant part of your life, you grow fond of it. When it's
finished, it feels like some kind of amorphous sculpture that
you've created. It has an abstract shape in your head that's
completely independent of its actual purpose. Elegant,
simple, beautiful. Then, only a year later, after making
dozens of pragmatic alterations to suit the people who use
it, not only has your Venus- de-Milo lost both arms, she also
has a giraffe's head sticking out of her chest and a cherubic
penis that squirts colored water into a plastic bucket. The
romance has become so painful that each day you struggle with
an overwhelming urge to smash the fucking thing to pieces
with a hammer." - Nick Foster ("Life as a programmer")


That is all :)

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.