I'd like to convert a number like 5.9.1 to a float or int value to compare it with another value
Asked
Active
Viewed 797 times
-2
-
What part of the number to you want? Or do you want all the dots removed? So you'd get 591? – Rich Apr 13 '14 at 13:47
-
1Well, what output value would you like for the above example? – Oliver Charlesworth Apr 13 '14 at 13:47
-
Let's say i've two numbers 5.9.1.1 which is less than 6.1.1, If i removed the dots and compared them the first one will be more. So i want a way to compare them as numbers. – user3528859 Apr 13 '14 at 13:48
-
The best you can do is remove the dots and then compare the numbers but because it seems like you can have multiple different dots its not going to be possible. – Rich Apr 13 '14 at 13:52
-
@rich: tell that to every program that can put version numbers in order properly ever. – Wooble Apr 13 '14 at 13:52
-
@Wooble: haha, this is why we should sack off market values and use build numbers :) – Rich Apr 13 '14 at 13:54
-
Your problem is that if you compare 5.9.1 and 5.10.1 you probably want them to sort in that order. If you blindly remove the dots you'll get the wrong order. And, of course 5.8.1.1 would sort after 5.9.1. You need to somehow do the operation "intelligently". – Hot Licks Apr 13 '14 at 14:06
-
@Wooble - No, use the Objective-C tag. Xcode is the IDE, and is not a factor here. – Hot Licks Apr 13 '14 at 14:09
-
Use `componentsSeparatedByString`, then iterate through the resulting array and convert each to numeric, then format as a 2 or 3-digit decimal string. Concatenate the decimal strings into a single string and do string compares, or put a dot in front, convert to float, and do float compares. If you know that there will never be more than 4/8 "divisions" you can put each numeric value in a binary byte and concatenate the bytes into an `int` or `long`, with the "bottom" end filled with zeros. – Hot Licks Apr 13 '14 at 14:26
-
(Or you can write a comparator that "walks" both strings and compares step-by-step.) – Hot Licks Apr 13 '14 at 14:27
-
@HotLicks: yes, that was my point. It was originally tagged Xcode and nothing else at all. – Wooble Apr 13 '14 at 14:35
-
2Possible duplicate: http://stackoverflow.com/questions/1978456/compare-version-numbers-in-objective-c – Wooble Apr 13 '14 at 14:37
-
@HotLicks I've give him an example of the approach I suggest in my updated answer now – Rich Apr 13 '14 at 14:54
-
@Wooble - Yeah, I forgot that compare with options:NSNumericSearch pretty much wraps it up. – Hot Licks Apr 13 '14 at 18:28
1 Answers
0
Use stringByReplacingOccurrencesOfString:withString:
NSString *dottedNumber = @"5.9.1";
NSString *undottedNumber = [dottedNumber stringByReplacingOccurrencesOfString:@"." withString:@""];
// undottedNumber will now be '591'
CGFloat number = [[@"0." stringByAppendingString:undottedNumber] floatValue];
That will then give you 0.591
, but from your recent comment you're looking to compare version strings which isn't an easy task. But this should (possibly!) cover most cases.
This will also work regardless of the localization as floatValue
states:
This method uses formatting information stored in the non-localized value So you don't have to worry about periods being used for thousand separators!
Note: This will not work however if you want to compare 5.12.1
against 5.2.0
, as 0.5121
is less than 0.520
To get around that you'd need to break it up into components and make sure each segment between the dots is the same length by padding with 0
s, ie convert 5.2.0
to 5.02.0
.
+(BOOL)isVersion:(NSString *)version laterThanVersion:(NSString *)anotherVersion
{
NSMutableArray *versionComponents = [[version componentsSeparatedByString:@"."] mutableCopy];
NSMutableArray *anotherVersionComponents = [[anotherVersion componentsSeparatedByString:@"."] mutableCopy];
for (NSUInteger i=0; i<MAX([versionComponents count], [anotherVersionComponents count]); i++) {
NSString *component = nil;
NSString *anotherComponent = nil;
if (i < [versionComponents count]) {
component = versionComponents[i];
}
if (i < [anotherVersionComponents count]) {
anotherComponent = anotherVersionComponents[i];
}
NSString *formatString = @"%%0%dd";
if ([component length] > [anotherComponent length]) {
// Pad out anotherComponent
anotherComponent = [NSString stringWithFormat:[NSString stringWithFormat:formatString, [component length]], [anotherComponent integerValue]];
} else {
// Pad out component
component = [NSString stringWithFormat:[NSString stringWithFormat:formatString, [anotherComponent length]], [component integerValue]];
}
if (i < [versionComponents count]) {
versionComponents[i] = component;
}
if (i < [anotherVersionComponents count]) {
anotherVersionComponents[i] = anotherComponent;
}
}
NSInteger versionInt = [[versionComponents componentsJoinedByString:@""] integerValue];
NSInteger anotherVersionInt = [[anotherVersionComponents componentsJoinedByString:@""] integerValue];
return versionInt > anotherVersionInt;
}
Example output:
+[self isVersion:5.9.1 laterThanVersion:5.6.0] => YES
+[self isVersion:5.10.1 laterThanVersion:5.6.0] => YES
+[self isVersion:5.10.1 laterThanVersion:5.10.10] => NO

Rich
- 8,108
- 5
- 46
- 59
-
-
@user3528859, Hot Licks make a valid point, I've updated to include the edge cases and a solution around them. – Rich Apr 13 '14 at 14:21
-
-
Of course, while you have the loop there you could just as well go ahead and do the compare, item by item. – Hot Licks Apr 13 '14 at 18:25