Advertisement

Parsing version number with leading zero to float

Started by May 18, 2018 08:09 AM
7 comments, last by Alberth 6 years, 3 months ago

I have a version number as string which is exactly like this: 16.041.3.137.

My goal is to parse each individual part into a floating point number, so you can use a >= as a comparison for each part.

Parsing the first, third and fourth part is easy, but the second one is a little tricky. If you parse it with base 10 you get a result of 4 - which is not correct.
The result of the second part "041" should be a exact floating point of 0.41. It should never round up or down.

So my question is, what do i need to do to construct a floating point manually: I have the count of leading zeros and the decimal value after that.

Is that possible?

Thanks!

How do you get "4" ? If you interpret it as a decimal number, you should get 41, if it gets interpreted as an octal number you'd get 4*8+1=33. Neither is value 4.

Anyway, the simplest is likely to check if there is a leading 0, and in that case insert a dot at the second position before you convert to a float.

Another option is to count the length of the string and divide the value 41 by 10**(length-1)=100   (One less than the length as the leading 0 is not part of the fraction.)

 

Advertisement

A version number as a float sounds like a bad idea at best. A slight imprecission causes the thing to blow up. 0.41 can for example not be represented exactly as a float.

Why not use integers? Keep an integer for the major, minor, patch etc level. Split the number at each dot and store those numbers.

04 and 041 are adjacent in the float representation, while 05 .. 040 would come in-between if you see them as integer values.

What might work is to keep the numbers as string, and sort them as text.

11 hours ago, Finalspace said:

If you parse it with base 10 you get a result of 4 - which is not correct.

0 * 10 + 0 = 0

0 * 10 + 4 = 4

4 * 10 + 1 = 41

Am I missing something?  What in the world are you using to parse these numbers?

Why are you using floating point?  All of the dotted-version-number schemes I've used use four integers.

"exact floating point of 0.41"

Floating point cannot represent 0.41 exactly.

There's a useful tool you can use to experiment with floating point:

https://www.h-schmidt.net/FloatConverter/IEEE754.html

"You entered: 0.41"

"Value actually stored in float: 0.4099999964237213134765625"

I would simple count for leading zeros to compute the floating point value:
 


atof(s) / powf(10.0, strspn(s, "0"))

 

Advertisement

Okay i think converting version number part to a float was a bad idea - after looking into https://www.h-schmidt.net/FloatConverter/IEEE754.html

I will go with two separate integers for each part -> Leading zero count and actual number.

I am not sure floating point precision is relevant in your case. The float number is not exactly the same as the decimal string representation, but that is common. It means that in general you cannot reproduce the version number from the floating point value.

For comparison purposes however, the only requirement you have is that the inexact floating point value still has the same ordering as the original version string. For 32-bit floats, error is around 10**-7, so as long as you have less than 7 significant digits, comparing will work.  (For safetly, you may want to limit to 5 or 6 digits, or switch to double representation which has an error of around 10**-15.)

Eg

041 -> 0.41 -> 0.4099999964237213134765625

042 -> 0.42 -> 0.4199999868869781494140625

but 041 < 042 <===> 0.4099999964237213134765625 < 0.4199999868869781494140625

This topic is closed to new replies.

Advertisement