-2

I need to compare versions of a software. The requirement is that I need to know if a given version is older (smaller), same or newer (higher) than another one. The version format is XX.X.XX where:

  • the first two digits are the major release. Major release can be between 01 and 99.
  • The next digit is the minor release and can be between 0 and 9.
  • The last two digits are the bugfix release and can be between 00 and 99. There can be no deviation from this format such as letters or two digits minor release.

The method I am using now is comparing each release number (major vs major, minor vs minor, bugfix vs bugfix) and returning a result based on that.

Knowing exactly the constraints of the version string format, can I just simply remove the dots, convert the version string (05211) to an integer and directly compare the two numbers resulted? Is there any case where this method would return an incorrect result?

2
  • 2
    Apple had some major (sorry, minor) problems when they released MacOS 10.4.10 an eternity ago. It turned out some apps did an alphabetic comparison and thought 10.4.10 was older than 10.4.2, which caused them to misbehave.
    – gnasher729
    Jan 26 at 11:03
  • Related: Version number comparison in python?
    – Stef
    Jan 26 at 12:30

4 Answers 4

11

In general, the dots are necessary, otherwise you couldn't distinguish 0.2.12 from 0.21.2 (and countless other examples).

If you can ensure that the major, minor and patchlevel revision are always exactly the length that you're expecting, then simplifying to a compound integer and comparing that would work. But this would mean that while your function seems to work with general semantic versioning numbers, in fact it depends on a rather arbitrary, non-obvious additional constraint that will almost certainly be forgotten by someone at some point.

This is a recipe for trouble much later on. The number of functions that seem to work with an arbitrary data type (in particular, strings) but actually work only for a slightly smaller subset of that type is legendary, and the source of many, many unexpected defects. It is almost certainly a better idea just to implement semantic versioning properly and be done with it.

2

I strongly recommend you extract the three digit sequences separately, ignore any knowledge how many digits they should have, and convert them into integers each. Then compare the highest integer, followed by the middle integer, followed by the last integer, and if there is a fourth one, compare that as well.

That way you don't suffer any surprises when the format changes slightly.

1

Your current way of comparing is the most robust way of doing a version compare, because it can also handle slightly malformed versions, like a minor version of 10 or a leading 0 missing somewhere.

If the requirements on the version number are as strict as you describe them, then doing a simple string compare on the version string (without even removing the dots) will give you a correct comparison result as well.

1

I agree 100% with Kilian Foth's answer, that doing what you are trying is likely to become error prone.

However, if you want to combine the version into a digit-only string for some technical reason, then what you can do almost safely is:

  • split the version string into 3 parts according to the dots

  • make sure the 3 parts are formatted to a certain number of digits (at least 2 digits for each part, I recommend 3 digits at a minimum)

  • combine the 3 parts as strings and convert the resulting string to a number

  • use the resulting number in a comparison with a second version number treated equally.

This is a simple one line in Python, for example:

 versionnumber = int(''.join([p.zfill(3) for p in version.split('.')]))

Joining with only five digits in total (XX.Y.ZZ => XXYZZ) is pretty risky, since it is not unlikely that, at some point in the near future, one of the parts with a length of 1 or 2 digits will be exceeded. Using 3x3 = 9 digits may be an acceptable risk, as long as the version numbers are increased manually, with a frequency of not more than one release per day. If the rightmost version number is, however, something like an automated build number, 3 digits are likely to become exceeded, and even 4 digits may not be sufficient all the time.

If you want to avoid those risks, then it is better to compare each part with each other individually.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.