Software, technology, sysadmin war stories, and more. Feed
Sunday, December 29, 2013

Floats and version numbers: just say no


See that floating point number? It probably means you harm. It wants to coerce you into doing things that look really nice and simple on the surface, but are really scaly and evil underneath. Have you ever seen that cartoon where one stick figure asks another how they manage to hold things when they have no fingers, let alone hands, and one whips out a magnifying glass to reveal tons of microscopic tentacle-ish things making it work? It's like that.

Let's say that 3.2 is the first two parts of a Linux kernel version. That is, it's the 3.2 from "3.2.45". Someone took that string, sliced it using the periods as separators, and then cast it to a float. Then they compared it to something else, like 3.0. 3.2 is in fact bigger than 3.0, and thus some feature is supported.

That's all well and good until 3.9 came and went, and 3.10 followed.

Guess what 3.10 really means when you're a float...

>>> s = '3.10.4'
>>> float(s[0:4])

... it's 3.1, more or less, and 3.1 is less than 3.2. Oops, better disable support for that feature!

Want to compare version numbers? You're already headed into a deep, dark pit of despair. It's just like date and time handling: seemingly simple because you do it every day, but a complete disaster once you try to get a computer to do it for you.

There are helper libraries. Hopefully whatever need you have will be satisfied by them. One thing is clear, though: chopping up a string and turning it into a float will yield pain. It's just a matter of when.


Homework for those who think this is no big deal: put the following versions in order using no other information about them.

1.0.0 1.01 1.02 1.1.15 1.1.15-pre1 1.1.15a 1.1.15b 1.1.15rc1 2.0.0 2.0.5-pre4-pre1 3.0 beta 1 3.0 beta 2 3.0 beta 3 3.0β4 4 5 6 7 10 11 12 13.1 13.37

I haven't even tried to be outlandish here. I think you can find at least one real-world example for every format I put up there in just the ~20 year histories of the Linux kernel and Slackware.