Objective C - iOS - verify float/double - ios

I am working on the infamous Stanford calculator assignment. I need to verify inputted numbers for valid float values, so we can handle numbers like 102.3.79.
To avoid having to write a little loop to count periods in the string, there's got to be a built-in function yeah?

You can use the C standard library function strtod(). It stops where it encounters an error, and sets its output argument accordingly. You can exploit this fact as follows:
- (BOOL)isValidFloatString:(NSString *)str
{
const char *s = str.UTF8String;
char *end;
strtod(s, &end);
return !end[0];
}

There's at least one fairly elegant solution for counting #"." in a string:
NSString *input = #"102.3.79";
if([[input componentsSeparatedByString:#"."] count] > 2) {
NSLog(#"input has too many points!");
}
Digging a little deeper... If you're looking to validate the whole string as a number, try configuring an NSNumberFormatter and call numberFromString: (NSNumberFormatter documentation).

Having gone through CS193P, I think the idea is to get comfortable with NSString and UILabel versus using C. I would look into having a simple decimal point BOOL flag, as buttons are pressed and you are concatenating the numbers 1- for use and 2- for display.
This will come in handy as well when you are doing other checks like hanging decimal points at the end of the number or allowing the user to backspace a number.
Edited for example:
Create an IBAction connected to each number button:
- (IBAction)numberButtonPressed:(UIButton *)sender
{
if([sender.titleLabel.text isEqualToString:#"."])
{
if (!self.inTheMiddleOfEnteringANumber)
self.display.text=[NSString stringWithString:#"0."];
else if (!self.decimalPointEntered)
{
self.display.text=[self.display.text stringByAppendingString:sender.titleLabel.text];
self.decimalPointEntered=TRUE;
}
}
self.inTheMiddleOfEnteringANumber=TRUE;
}

-(BOOL) isNumeric:(NSString*)string {
NSNumberFormatter *formatter = [NSNumberFormatter new];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber *number = [formatter numberFromString:string];
[formatter release]; // if using ARC remove this line
return number!=nil;
}
-(BOOL) isFloat:(NSString*)string {
NSScanner *scanner = [NSScanner scannerWithString:string];
[scanner scanFloat:NULL];
return [scanner isAtEnd];
}

Related

convert NSString to long value [duplicate]

How can I convert a NSString containing a number of any primitive data type (e.g. int, float, char, unsigned int, etc.)? The problem is, I don't know which number type the string will contain at runtime.
I have an idea how to do it, but I'm not sure if this works with any type, also unsigned and floating point values:
long long scannedNumber;
NSScanner *scanner = [NSScanner scannerWithString:aString];
[scanner scanLongLong:&scannedNumber];
NSNumber *number = [NSNumber numberWithLongLong: scannedNumber];
Thanks for the help.
Use an NSNumberFormatter:
NSNumberFormatter *f = [[NSNumberFormatter alloc] init];
f.numberStyle = NSNumberFormatterDecimalStyle;
NSNumber *myNumber = [f numberFromString:#"42"];
If the string is not a valid number, then myNumber will be nil. If it is a valid number, then you now have all of the NSNumber goodness to figure out what kind of number it actually is.
You can use -[NSString integerValue], -[NSString floatValue], etc. However, the correct (locale-sensitive, etc.) way to do this is to use -[NSNumberFormatter numberFromString:] which will give you an NSNumber converted from the appropriate locale and given the settings of the NSNumberFormatter (including whether it will allow floating point values).
Objective-C
(Note: this method doesn't play nice with difference locales, but is slightly faster than a NSNumberFormatter)
NSNumber *num1 = #([#"42" intValue]);
NSNumber *num2 = #([#"42.42" floatValue]);
Swift
Simple but dirty way
// Swift 1.2
if let intValue = "42".toInt() {
let number1 = NSNumber(integer:intValue)
}
// Swift 2.0
let number2 = Int("42')
// Swift 3.0
NSDecimalNumber(string: "42.42")
// Using NSNumber
let number3 = NSNumber(float:("42.42" as NSString).floatValue)
The extension-way
This is better, really, because it'll play nicely with locales and decimals.
extension String {
var numberValue:NSNumber? {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
return formatter.number(from: self)
}
}
Now you can simply do:
let someFloat = "42.42".numberValue
let someInt = "42".numberValue
For strings starting with integers, e.g., #"123", #"456 ft", #"7.89", etc., use -[NSString integerValue].
So, #([#"12.8 lbs" integerValue]) is like doing [NSNumber numberWithInteger:12].
You can also do this:
NSNumber *number = #([dictionary[#"id"] intValue]]);
Have fun!
If you know that you receive integers, you could use:
NSString* val = #"12";
[NSNumber numberWithInt:[val intValue]];
Here's a working sample of NSNumberFormatter reading localized number NSString (xCode 3.2.4, osX 10.6), to save others the hours I've just spent messing around. Beware: while it can handle trailing blanks ("8,765.4 " works), this cannot handle leading white space and this cannot handle stray text characters. (Bad input strings: " 8" and "8q" and "8 q".)
NSString *tempStr = #"8,765.4";
// localization allows other thousands separators, also.
NSNumberFormatter * myNumFormatter = [[NSNumberFormatter alloc] init];
[myNumFormatter setLocale:[NSLocale currentLocale]]; // happen by default?
[myNumFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
// next line is very important!
[myNumFormatter setNumberStyle:NSNumberFormatterDecimalStyle]; // crucial
NSNumber *tempNum = [myNumFormatter numberFromString:tempStr];
NSLog(#"string '%#' gives NSNumber '%#' with intValue '%i'",
tempStr, tempNum, [tempNum intValue]);
[myNumFormatter release]; // good citizen
I wanted to convert a string to a double. This above answer didn't quite work for me. But this did: How to do string conversions in Objective-C?
All I pretty much did was:
double myDouble = [myString doubleValue];
Thanks All! I am combined feedback and finally manage to convert from text input ( string ) to Integer. Plus it could tell me whether the input is integer :)
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber * myNumber = [f numberFromString:thresholdInput.text];
int minThreshold = [myNumber intValue];
NSLog(#"Setting for minThreshold %i", minThreshold);
if ((int)minThreshold < 1 )
{
NSLog(#"Not a number");
}
else
{
NSLog(#"Setting for integer minThreshold %i", minThreshold);
}
[f release];
I think NSDecimalNumber will do it:
Example:
NSNumber *theNumber = [NSDecimalNumber decimalNumberWithString:[stringVariable text]]];
NSDecimalNumber is a subclass of NSNumber, so implicit casting allowed.
What about C's standard atoi?
int num = atoi([scannedNumber cStringUsingEncoding:NSUTF8StringEncoding]);
Do you think there are any caveats?
You can just use [string intValue] or [string floatValue] or [string doubleValue] etc
You can also use NSNumberFormatter class:
you can also do like this code 8.3.3 ios 10.3 support
[NSNumber numberWithInt:[#"put your string here" intValue]]
NSDecimalNumber *myNumber = [NSDecimalNumber decimalNumberWithString:#"123.45"];
NSLog(#"My Number : %#",myNumber);
Try this
NSNumber *yourNumber = [NSNumber numberWithLongLong:[yourString longLongValue]];
Note - I have used longLongValue as per my requirement. You can also use integerValue, longValue, or any other format depending upon your requirement.
Worked in Swift 3
NSDecimalNumber(string: "Your string")
I know this is very late but below code is working for me.
Try this code
NSNumber *number = #([dictionary[#"keyValue"] intValue]]);
This may help you. Thanks
extension String {
var numberValue:NSNumber? {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
return formatter.number(from: self)
}
}
let someFloat = "12.34".numberValue

How to not show unnecessary zeros when given integers but still have float answers when needed

I have an app I'm developing and one of my features is giving answers in float or double values when needed and an integer when the answer is a whole number
so for example if the answer comes out to 8.52 the answer becomes 8.52 but when the answer is 8 the answer is 8 instead of 8.0000, i don't want it to show all the extra 0s.
- (IBAction) equalsbutton {
NSString *val = display.text;
switch(operation) {
case Plus :
display.text= [NSString stringWithFormat:#"%qi",[val longLongValue]+[storage longLongValue]];
case Plus2 :
display.text= [NSString stringWithFormat:#"%f",[val doubleValue]+[storage doubleValue]];
this code doesn't seem to work
These specifiers are standard IEEE format specifiers, which means that you can do things like %.2f to only show 2 decimal places on a float variable.
You could also convert it into an int, and then use the %d format specifier if you wanted to do it that way.
Here's also Apple's documentation on the subject.
EDIT: Based on your comment on the other post, it looks like you're looking for %g, which will essentially remove the extraneous 0's from floats.
display.text= [NSString stringWithFormat:#"%g",[val doubleValue]+[storage doubleValue]];
I found the answer here: Use printf to format floats without decimal places if only trailing 0s
EDIT Formatting
Here is a way that I did this when I needed to display currency (but whole numbers if the currency was a round number.
First we get the money amount as a string
NSString *earnString = _money.payout.displayableAmount;
NSMutableString *strippedString = [NSMutableString
stringWithCapacity:earnString.length];
//scan the string to remove anything but the numbers (including decimals points)
NSScanner *scanner = [NSScanner scannerWithString:earnString];
NSCharacterSet *numbers = [NSCharacterSet
characterSetWithCharactersInString:#"0123456789"];
while ([scanner isAtEnd] == NO) {
NSString *buffer;
if ([scanner scanCharactersFromSet:numbers intoString:&buffer]) {
[strippedString appendString:buffer];
} else {
[scanner setScanLocation:([scanner scanLocation] + 1)];
}
}
//create an int with this new string
int earnInt = [strippedString intValue];
//if the string is less than 100 then we only had "change" so display that amount
if(earnInt < 100){
//Dollar amount is less then dollar display just the cents and the cent symbol
NSString *centString = [NSString stringWithFormat:#"%i¢", earnInt];
earnAmount.text = centString;
//if we have a number evenly divisible by 100 then we have whole dollar amount, display that properly
}else if(earnInt % 100 == 0){
//The amount is exactly a dollar, display the whole number
NSString *wholeDollar = [NSString stringWithFormat:#"$%i", (earnInt/100)];
earnAmount.text = wholeDollar;
//finally if we have a mixed number then put them back together with the decimal in-between.
}else{
//Dollar amount is not exactly a dollar display the entire amount
NSString *dollarString = [NSString stringWithFormat: #"$%0d.%02d", (earnInt / 100), (earnInt % 100)];
earnAmount.text = dollarString;
}
Hopefully this helps you out...
You can try this method call:
[NSString stringWithFormat:#"%.0f", [val doubleValue] + [storage doubleValue]];
Easiest way, is NSNumberFormatter. It will only display the decimal if needed. Example (Swift):
let num1: Double = 5
let num2: Double = 5.52
let numberFormatter = NSNumberFormatter()
numberFormatter.numberStyle = .DecimalStyle
print(numberFormatter.stringFromNumber(NSNumber(double: num1)))
print(numberFormatter.stringFromNumber(NSNumber(double: num2)))
This will print 5 and then 5.52.

How do I prevent more than 2 numbers after a decimal point in UITextField?

Right Now I am making an app where the user is required to input a currency value, decimal point optional, into a UITextField. My problem comes up when I try to prevent more than 2 numbers after a given decimal point while at the same time preventing more than one decimal point. I have researched around the web and couldn't find an exact answer. I have found that I will most probably need to use the shouldChangeCharactersInRange, but I'm not sure how to use it exactly...
Thanks,
Virindh Borra
You would use a number formatter:
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setPositiveFormat:#"###0.##"];
NSString *formattedNumberString = [numberFormatter stringFromNumber:#122344.4563];
NSLog(#"formattedNumberString: %#", formattedNumberString);
// Output for locale en_US: "formattedNumberString: formattedNumberString: 122,344.45"
from: https://developer.apple.com/library/ios/documentation/cocoa/Conceptual/DataFormatting/Articles/dfNumberFormatting10_4.html#//apple_ref/doc/uid/TP40002368-SW1
You would put this in one of your UITextFieldDelegate methods like textField:shouldChangeCharactersInRange:replacementString:. Get the most recent string by doing: NSString *s = [textField.text stringByReplacingCharactersInRange:range withString:string]; Then you would get the number value of that string with #([s floatValue]), and then use the number formatter like shown above, then put it in the text field.
I would do some checking to make sure they have entered in at least two digits after the decimal before messing with their input. But this would be the correct, localized way to do it.
// add a notification & use following function:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(textIsChanged:) name:UITextFieldTextDidChangeNotification object:nil];
-(void)textIsChanged:(NSNotification*)notification
{
NSString * currentText = yourTextField.text;
if ([currentText rangeOfString:#"."].location != NSNotFound)
{
NSArray *arr = [currentText componentsSeparatedByString:#"."];
if(arr.count == 2)
{
NSString *afterDecimalPart = [arr objectAtIndex:1];
if(afterDecimalPart.length > 2)
{
currentText = [currentText substringToIndex:currentText.length-1];
yourTextField.text = currentText;
}
}
}
}

"isnan" doesn't seem to work

Simply trying to catch non numeric input
Read MANY items . Tried decimalDigitCharacterSet (found it hard to believe that something that starts with the word "decimal" doesn't contain a decimal). Tried mutable character set to add the decimal. Been working to include "10.5" with "96" and still exclude "abc".
the following code produces "IS a number" no matter what I put in textbox1
double whatTheHey;
whatTheHey = _textBox1.text.doubleValue;
if isnan(whatTheHey) {
_textBox2.text = #"NOT a number > ";
}
if (!isnan(whatTheHey)) {
_textBox2.text = #"IS a number > ";
}
10.5 , 99 , qwerty all yield "IS a number"
This seems like a heck of a lot of work just to catch non numeric input.
Does anybody have any blatantky simple examples of working code to catch non numeric but accept numbers with decimal in them?
NaN does not literally mean "anything that is not a number". It is the name of a specific value — namely one floats can have after certain indeterminate operations such as dividing zero by zero or taking the square root of a negative number. See the Wikipedia entry for more history.
To actually parse the numeric value of a string, you probably want to look into NSNumberFormatter:
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber *a = [numberFormatter numberFromString:#"10.5"];
NSNumber *b = [numberFormatter numberFromString:#"96"];
NSNumber *c = [numberFormatter numberFromString:#"abc"];
NSLog(#"a: %#, b: %#, c: %#", a, b, c);
Yields:
a: 10.5, b: 96, c: (null)
A simpler (if less flexible) solution that meets your specific criteria might be:
BOOL isNumber(NSString *aString){
return [aString integerValue] || [aString floatValue];
}
But if you're writing for iOS (or OS X), you really ought to get comfortable with the NSFormatters. They'll make your life a lot easier.
to check wether a string is numeric or not use the following piece of code.
NSString *newString = #"11111";
NSNumberFormatter *nf = [NSNumberFormatter new];
BOOL isDecimal = [nf numberFromString:newString] != nil;
Try this. I think it should do what you need:
- (BOOL)isStringNumeric:(NSString *)input {
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
NSNumber *number = [numberFormatter numberFromString:input];
return (number != nil);
}

NSNumber storing float. Please NO scientific notation?

My code looks like this
NSNumber *inputToNumber = [NSNumber numberWithFloat:[textField.text floatValue]];
the value from the textfield is actually a telephone number. It's stored in NSNumber as an annoying (2.0)78966e+08
How can I just get NSNumber to store it as 0207896608?
I think that the basic idea to store a phone number into a NSNumber is flawed:
how do you discriminate between numbers with or without leading 0 ?
how do you store phone numbers from foreign countries ?
I would use NSString in place of NSNumber.
Just because it's called a number doesn't mean a "telephone number" is a number in the same sense that "5" or "pi" are.
Either you should treat a telephone number as a string, or you should create a TelephoneNumber model class to represent each one.
Consider that there are places in the world where numbers don't have leading 0's and where a number with a leading 0 is not the same as the same number without a leading 0.
05843924 != 5843924
So stop being lazy with that NSNumber hacks and build your own phone-number class.
Scientific notation is used in may computer languages as the default output of very large (or very small) numbers. If you want the number to be output as a decimal, you need to specify the output format (the implementation varies by language.)
Also, julesjacobs is correct. You should not use FLOAT for a phone number as it is subject to binary rounding errors. Using INT or STRING will save you lots of headaches.
If you need to be able to deal with it as numbers maybe you should break it up into its parts, and store each part as an integer.
01112223333
country code 0
area code 111
prefix 222
number 3333
Or you could store the whole thing as a string if you don't need to manipulate it.
Are you storing a phone number in a float? You should consider using an integer or string. Perhaps:
NSNumber *inputToNumber = [NSNumber numberWithInt:[textField.text intValue]];
Hey Guys what do you think of this, It seems to full-fill my purposes. Only UK at the moment so will worry about localization when I get a chance.
I use this to get to store the number
NSNumber *inputToNumber = [NSNumber numberWithLongLong:(long long)[[textField.text stringByReplacingOccurrencesOfString:#" " withString:#""] longLongValue]];
And this method formats my telephone number and takes care of the preceeding 0 mentioned.
-(NSString *)phoneNumberString:(NSNumber *)phoneNumber {
//Add a zero because NSNumber won't save a preceeding zero
NSString *telephoneString = [[NSString alloc] initWithFormat:#"0%#", [phoneNumber stringValue]];
if (telephoneString.length >= 4) {
NSString *firstPart = [[NSString alloc] initWithString: [telephoneString substringToIndex:4]];
NSString *secondPart = [[NSString alloc] initWithString: [telephoneString substringFromIndex:4]];
//Add the two parts together with a space inbetween
NSString *formattedTelephoneString = [NSString stringWithFormat:#"%# %#", firstPart, secondPart];
//send it back to the cellForRow TableCell Method
[firstPart release];
[secondPart release];
[telephoneString release];
return formattedTelephoneString;
}
else {
return telephoneString;
}
}
Thanks for all the comments. I'm gonna mark the answer as whoever suggested NSString as I fear I will revert to using NSString for this instead of my above workaround.

Resources