7

I need to be able to convert a version string to an integer. I've decided I will follow semantic versioning so version strings will be of the type x.y.z.

Initially I thought a simple algorithm like int = x * 10^6 + y * 10^3 + z would be sufficient and it most probably will be since I've never seen software with a three digit major/minor/patch value, however theoretically it is possible for such algorithm to fail.

Lets suppose we have versions 2.0.0 and 1.1000.0, in this case the integers would be

int(2.0.0)    = 2 * 10^6 + 0 * 10^3 + 0    = 2000000
int(1.1000.0) = 1 * 10^6 + 1000 * 10^3 + 0 = 2000000

Clearly the algorithm is flawed, I want to ask if there is a known such algorithm that I could use.

Again I would probably be OK performing the calculation this way but I'm interested to find out if there is a bulletproof way?

  • 3
    Your main problem is that a version string is not a number. It is a string. Just because a string only contains digits doesn't make it a number. A phonenumber is still a string. If it is because you need to compare two versions, then compare each part individually. – Bent Mar 24 '16 at 18:19
  • @Bent I need to be able to find the next version of a given API in a database given a known version, I figured the easiest way would be to convert the version to some integer based on a law and use that instead of some complex logic in SQL which would look horrible. I guess I could just limit version components to 1000 or more extreme case 10000 and deal with that. – php_nub_qq Mar 24 '16 at 20:28
  • 2
    I would still not use a simple integer comparison. I would create a function that compares the integer value before the period. If that is equal then the value after the first and before the second period. And so on. And don't rely on there only being 2 periods or even the same amount of periods in both version strings. – Bent Mar 24 '16 at 20:52
  • 1
    @Bent: Actually, it's more like a tuple (Nat × Nat × Nat × String). – Jörg W Mittag Mar 25 '16 at 1:13
  • What you want is impossible unless you limit the component numbers, and then it's trivial. The SQL is not so bad, depending on the database engine. – kevin cline Apr 1 '16 at 1:06
7

No, there's no bulletproof way unless you know the maximum values in advance (the maximum number of digits per component). You will also need that information to decode the number.

You're trying to represent something using positional notation, so the positions in your single integer have an inherent meaning. There is extra information within the "x.y.z" version string (the dots separating the components), which is lost when you do your conversion to a single integer.

4

If the only requirement is that each version string has a unique integer identifier, you can use a function like:

int(x.y.z) = 2^x * 3^y * 5^z

This is easily reversible by finding the prime factorization of the integer, but doesn't have the same ordering as the version strings.

Edit: If the size of the integer is a concern, find the binary representation for each element of the tuple

x -> ...x3 x2 x1 x0
y -> ...y3 y2 y1 y0
z -> ...z3 z2 z1 z0

then interleave the bits

output = ... x3 y3 z3 x2 y2 z2 x1 y1 z1 z0 y0 z0

This should be more space efficient than storing a version string.

  • 2
    Brilliant in theory, but could be a problem if there's going to be a large number of patch releases: You'll need quite a few digits to represent version 6.0.103 – Solomon Slow Mar 24 '16 at 19:56
  • 1
    I think you wanted multiplications instead of additions. With the current formula, 1.1.0 gives the same result as 0.0.1. I agree with James that this will however quickly give huge numbers. – user2313067 Mar 25 '16 at 16:03
0

In addition to the other answer, consider that discarding labels like "alpha", etc. is not a good idea if you have to compare versions. Instead of using strings, consider parsing a version into a structured internal data:

(major: 3, minor: 0, patch: 0, label: "alpha")

And define a custom lexicographic sort for comparing them.

-1

Don't.

You didn't explain in your question why you want to do this but it is probably a bad idea. I think that whatever usecase you are thinking of, it is probably better to handle it a different way.

If you really want to map version numbers to integers and have them be unique and in order you must know how many digits each part of the version string can have. Then you could do something like you mentioned in your question.


Additionally, in terms of order, I am not really sure what should come first:

Version 1.0 - Released in Dec 2000
Version 1.1 - Released in Dec 2001
Version 2.0 - Released in Dec 2002
Version 1.2 - Released in Dec 2014

Do you want to sort by release date or do you want to sort by major version, followed by minor version, followed by ... ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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