Finding out if a string is numeric or not

How to check if a string contains only numbers. I am taking a substring from a string and want to check if it is a numeric substring or not.

NSString *newString = [myString substringWithRange:NSMakeRange(2,3)]; 
+89
ios objective-c iphone cocoa-touch nsstring
May 22 '11 at 23:04
source share
17 answers

Here's one way that doesn't rely on the limited accuracy of trying to parse a string as a number:

 NSCharacterSet* notDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet]; if ([newString rangeOfCharacterFromSet:notDigits].location == NSNotFound) { // newString consists only of the digits 0 through 9 } 

See +[NSCharacterSet decimalDigitCharacterSet] and -[NSString rangeOfCharacterFromSet:] .

+230
May 22 '11 at 23:13
source share

I would suggest using the numberFromString: method numberFromString: from the NSNumberFormatter class, as if this number is not valid, it will return zero; otherwise, it will return an NSNumber to you.

 NSNumberFormatter *nf = [[[NSNumberFormatter alloc] init] autorelease]; BOOL isDecimal = [nf numberFromString:newString] != nil; 
+31
May 22 '11 at 23:10
source share

Validated by a regular expression, pattern "^[0-9]+$" using the following method -validateString:withPattern:

 [self validateString:"12345" withPattern:"^[0-9]+$"]; 
  1. If "123.123" is considered
    • With the pattern "^[0-9]+(.{1}[0-9]+)?$"
  2. If exactly 4 digits, without "." ,
    • With the pattern "^[0-9]{4}$" .
  3. If digits are digits without "." and the length is from 2 to 5.
    • With the pattern "^[0-9]{2,5}$" .

Regular expression can be checked on the online website .

The auxiliary function is as follows.

 // Validate the input string with the given pattern and // return the result as a boolean - (BOOL)validateString:(NSString *)string withPattern:(NSString *)pattern { NSError *error = nil; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&error]; NSAssert(regex, @"Unable to create regular expression"); NSRange textRange = NSMakeRange(0, string.length); NSRange matchRange = [regex rangeOfFirstMatchInString:string options:NSMatchingReportProgress range:textRange]; BOOL didValidate = NO; // Did we find a matching range if (matchRange.location != NSNotFound) didValidate = YES; return didValidate; } 



Swift 3 version:

Test on the playground.

 import UIKit import Foundation func validate(_ str: String, pattern: String) -> Bool { if let range = str.range(of: pattern, options: .regularExpression) { let result = str.substring(with: range) print(result) return true } return false } let a = validate("123", pattern: "^[0-9]+") print(a) 
+10
Feb 16 '16 at 7:19
source share

You can create NSScanner and just view the line:

 NSDecimal decimalValue; NSScanner *sc = [NSScanner scannerWithString:newString]; [sc scanDecimal:&decimalValue]; BOOL isDecimal = [sc isAtEnd]; 

Check out the NSScanner documentation for more methods.

+8
May 22 '11 at 23:08
source share

I think the easiest way to verify that each character in a given string is numeric is probably:

 NSString *trimmedString = [newString stringByTrimmingCharactersInSet:[NSCharacterSet decimalDigitCharacterSet]]; if([trimmedString length]) { NSLog(@"some characters outside of the decimal character set found"); } else { NSLog(@"all characters were in the decimal character set"); } 

Use one of the other NSCharacterSet factory methods if you want complete control over valid characters.

+6
May 22 '11 at 23:14
source share

Swift 3 solution, if you need to verify that the string contains only numbers:

 CharacterSet.decimalDigits.isSuperset(of: CharacterSet(charactersIn: myString)) 
+6
Mar 31 '17 at 11:15
source share

This original question was about Objective-C, but it was also published a few years before Swift was announced. So, if you come here from Google and are looking for a solution that uses Swift, you are here:

 let testString = "12345" let badCharacters = NSCharacterSet.decimalDigitCharacterSet().invertedSet if testString.rangeOfCharacterFromSet(badCharacters) == nil { print("Test string was a number") } else { print("Test string contained non-digit characters.") } 
+5
Dec 18 '15 at 11:49
source share

to be clear, these functions are for integers in strings.

heres a little helper category based on John's answer above:

in .h file

 @interface NSString (NumberChecking) +(bool)isNumber:(NSString *)string; @end 

in .m file

 #import "NSString+NumberChecking.h" @implementation NSString (NumberChecking) +(bool)isNumber { if([self rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]].location == NSNotFound) { return YES; }else { return NO; } } @end 

using:

 #import "NSString+NumberChecking.h" if([someString isNumber]) { NSLog(@"is a number"); }else { NSLog(@"not a number"); } 
+4
Feb 04 '14 at 17:59
source share

Swift 3's solution might be this:

 extension String { var doubleValue:Double? { return NumberFormatter().number(from:self)?.doubleValue } var integerValue:Int? { return NumberFormatter().number(from:self)?.intValue } var isNumber:Bool { get { let badCharacters = NSCharacterSet.decimalDigits.inverted return (self.rangeOfCharacter(from: badCharacters) == nil) } } } 
+4
Oct 28 '16 at 11:13
source share

John Kalsbek's answer is almost correct, but it does not contain some extreme cases of Unicode.

According to the documentation for decimalDigitCharacterSet , this set includes all characters classified by Unicode as Nd . Thus, their answer will accept, among other things:

  • เฅง + 0967 Devanagari SYMBOL ONE)
  • U (U + 1811 แ ‘ ONE)
  • ๐Ÿ™ (U + 1D7D9 MATH DIGITAL DOUBLE LINE)

Although in a sense this is correct - every character in Nd mapped to a decimal digit - this is almost certainly not what the asker expected. At the time of writing, there were 610 code points classified as Nd , only ten of which are expected characters from 0 (U + 0030) to 9 (U + 0039).

To solve this problem, just specify exactly those characters that are acceptable:

 NSCharacterSet* notDigits = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789"] invertedSet]; if ([newString rangeOfCharacterFromSet:notDigits].location == NSNotFound) { // newString consists only of the digits 0 through 9 } 
+2
Dec 25 '18 at 23:36
source share

Another option:

 - (BOOL)isValidNumber:(NSString*)text regex:(NSString*)regex { @try { NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex]; return [predicate evaluateWithObject:text]; } @catch (NSException *exception) { assert(false); return NO; } } 

Usage example:

 BOOL isValid = [self isValidNumber:@"1234" regex:@"^[0-9]+$"]; 
+1
Mar 09 '17 at 3:52 on
source share

Checking if a string is a number may be useful

 int i = [@"12.3" rangeOfCharacterFromSet: [ [NSCharacterSet characterSetWithCharactersInString:@"0123456789."] invertedSet] ].location; if (i == NSNotFound) { //is a number } 
0
Sep 27 '14 at 11:47
source share

Quick expansion:

 extension NSString { func isNumString() -> Bool { let numbers = NSCharacterSet(charactersInString: "0123456789.").invertedSet let range = self.rangeOfCharacterFromSet(numbers).location if range == NSNotFound { return true } return false } } 
0
Oct 17 '16 at 7:46
source share

For Swift 3

 var onlyDigits: CharacterSet = CharacterSet.decimalDigits.inverted if testString.rangeOfCharacter(from: onlyDigits) == nil { // String only consist digits 0-9 } 
0
Mar 16 '17 at 14:21
source share

Extension of @John Calsbeek's answer and clarification of comments by @Jeff and @gyratory circc .

 + (BOOL)doesContainDigitsOnly:(NSString *)string { NSCharacterSet *nonDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet]; BOOL containsDigitsOnly = [string rangeOfCharacterFromSet:nonDigits].location == NSNotFound; return containsDigitsOnly; } + (BOOL)doesContainNonDigitsOnly:(NSString *)string { NSCharacterSet *digits = [NSCharacterSet decimalDigitCharacterSet]; BOOL containsNonDigitsOnly = [string rangeOfCharacterFromSet:digits].location == NSNotFound; return containsNonDigitsOnly; } 

As category methods for NSString

You can add the following:
 - (BOOL)doesContainDigitsOnly { NSCharacterSet *nonDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet]; BOOL containsDigitsOnly = [self rangeOfCharacterFromSet:nonDigits].location == NSNotFound; return containsDigitsOnly; } - (BOOL)doesContainNonDigitsOnly { NSCharacterSet *digits = [NSCharacterSet decimalDigitCharacterSet]; BOOL containsNonDigitsOnly = [self rangeOfCharacterFromSet:digits].location == NSNotFound; return containsNonDigitsOnly; } 
0
Jul 27 '17 at 16:43
source share

If you have numbers from mixed languages that use (or don't use) 0-9 formats, you will need to run a regular expression that will search for any number, then you need to convert all the numbers to 0-9 format (if you need the actual value ):

 // Will look for any language digits let regex = try NSRegularExpression(pattern: "[^[:digit:]]", options: .caseInsensitive) let digitsString = regex.stringByReplacingMatches(in: string, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, string.count), withTemplate: "") // Converting the digits to be 0-9 format let numberFormatter = NumberFormatter() numberFormatter.locale = Locale(identifier: "EN") let finalValue = numberFormatter.number(from: digitsString) if let finalValue = finalValue { let actualValue = finalValue.doubleValue } 
0
Jan 07 '19 at 11:18
source share

The easiest and most reliable way is to use Double , if the result is nil - it cannot be converted to a valid number.

 let strings = ["test", "123", "123.2", "-123", "123-3", "123..22", ".02"] let validNumbers = strings.compactMap(Double.init) print(validNumbers) // prints [123.0, 123.2, -123.0, 0.02] 

More information in the documentation: https://developer.apple.com/documentation/swift/double/2926277-init

0
Apr 28 '19 at 13:35
source share



All Articles