Float value resets after Adding - ios

I start off with a number, lets say 250. I add all sorts of numbers, but anytime I add a high number like 2,000 it adds correctly. Then I add 3. The new number comes out to 5 like it thought 2,000 was 2.0. I do not know why it is doing this.
float start = self.amountLabel.text.floatValue;
float changeAmount = self.amountField.text.floatValue;
float newValue;
if (determConfirm == 1) {
newValue = start + changeAmount;
} else {
newValue = start - changeAmount;
}
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
[formatter setMaximumFractionDigits:5];
[formatter setRoundingMode: NSNumberFormatterRoundUp];
NSString *numberString = [formatter stringFromNumber:[NSNumber numberWithFloat:newValue]];
[[NSUserDefaults standardUserDefaults] setValue:numberString forKey:#"newValue"];
[[NSUserDefaults standardUserDefaults] synchronize];
self.amountLabel.text = numberString;
self.amountField.text = #"0.00";
[self.amountField resignFirstResponder];

The problem is the use of floatValue to convert the formatted number text to a number. floatValue only works as expected if the text is unformatted (no commas) and uses the period for the decimal separator.
Since you store a formatted number in the field, it only works with small numbers and in certain locales.
Replace your use of floatValue on the text with the same NSNumberFormatter used to format the number. Use it to parse the text and give you an NSNumber (which you can then call floatValue on).

Just a guess as it's hard by looking at your code, but maybe you want this:
float newValue = start;
if (determConfirm == 1) {
newValue += changeAmount;
} else {
newValue -= changeAmount;
}

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

Converting NSString number to float

I am having difficulties converting NSString's that have numbers into floats or something more useful.
I have tried the following code:
NSString *mystring = #"123"
int currentBidAmount = [myString integerValue];
No problem there.
Then float
NSString *mystring = #"123.95"
float currentBidAmount = [myString floatValue];
Again, no problem
However when myString has three decimals - I get an inaccurate number. For Example:
NSString *mystring = #"1.123.95"
float currentBidAmount = [myString floatValue];
It prints out: 1
Can someone tell me what I am doing wrong here?
The goal is to have two NSStrings - get their values and add them up for a total amount. So I need more accuracy than just I am getting now.
While you can get an NSString integer or floatValue you should use NSNumberFormatterfor that. Why? The decimal and grouping separator varies between countries and the floatValue code does only account for . as decimal separator. So users with a locale using a , are doomed.
How to:
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
float myFloat = [numberFormatter numberFromString:myString].floatValue;
Read up on various settings here: https://developer.apple.com/library/ios/documentation/cocoa/reference/foundation/classes/NSNumberFormatter_Class/Reference/Reference.html
you can't put two commas for a float value
this code works fins:
NSString *example = #"13124.4153";
float floatValue = [example floatValue];
NSLog(#"value = %f", floatValue);
Thanks for the help guys. I managed to solve the problem. The issue was the grouping separator. It separated by leaving a space. So this is why I had inaccurate numbers. Now, since I needed all my numbers to stay in this format but change when I was doing calculations (Adding sums together - I wrote a class method that looks like this:
(NSString *)getDisplayAmountStringWithValue: (NSString *)value Currency: (NSString *)currency
{
NSDecimalNumber *decimalValue = [NSDecimalNumber decimalNumberWithString:[value stringByReplacingOccurrencesOfString:#"," withString:#""]];
if ([decimalValue isEqualToNumber:[NSDecimalNumber notANumber]]){
decimalValue = [NSDecimalNumber decimalNumberWithString:#"0"];
}
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
[formatter setGroupingSeparator:#" "];
[formatter setDecimalSeparator:#"."];
[formatter setMaximumFractionDigits:2];
[formatter setMinimumFractionDigits:2];
if ([currency length] > 0){
[formatter setPositivePrefix:[NSString stringWithFormat:#"%#", currency]];
[formatter setNegativePrefix:[NSString stringWithFormat:#"%#-", currency]];
}else {
[formatter setGroupingSeparator:#""];
}
NSString *newNumberString = [formatter stringFromNumber:decimalValue];
return newNumberString;
}
Notice the if statement. I simply remove the space if I don't supply a currency (Which is not needed when adding sums together) - this along with my existing code, works perfectly.
Thanks for all the tips.

"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);
}

Having trouble using NSNumberFormatter for currency conversion in iOS

I have a UITextField that receives numeric input from the user in my application. The values from this textfield then get converted into currency format using NSNumberFormatter within my shouldChangeCharactersInRange delegate method. When I enter the number "12345678", the number gets correctly converted to $123456.78 (the numbers are entered one digit at a time, and up to this point, everything works smoothly). However, when I enter another digit after this (e.g. 9), rather than displaying "1234567.89", the number "1234567.88" is displayed. If I enter another number after that, a totally different numbers after this (I'm using the number key pad in the application to enter the numbers. Here is the code that I have:
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
modifiedValue = [formatter stringFromNumber:[NSNumber numberWithFloat:[modifiedValue floatValue]]];
textField.text = modifiedValue;
The line that causes this unusual conversion is this one:
modifiedValue = [formatter stringFromNumber:[NSNumber numberWithFloat:[modifiedValue floatValue]]];
Can anyone see why this is?
It's likely to be a rounding error when doing the string->float conversion. You shouldn't use floats when dealing with currency. You could use a NSDecimalNumber instead.
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
// Below 2 lines if converting from a "currency" string
NSNumber *modifiedNumber = [formatter numberFromString:modifiedValue]; // To convert from the currency string to a number object
NSDecimalNumber *decimal = [NSDecimalNumber decimalNumberWithDecimal:[modifiedNumber decimalValue]];
// OR the below line if converting from a non-currency string
NSDecimalNumber *decimal = [NSDecimalNumber decimalNumberWithString:modifiedValue];
modifiedValue = [formatter stringFromNumber:decimal]; // Convert the new decimal back to a currency string
You may also consider making the number formatter lenient - often helps with user entered data.
[formatter setLenient:YES];
When I'm running number conversions to currency, I usually run this code:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSString *text = _textField.text;
NSString *decimalSeperator = #".";
NSCharacterSet *charSet = nil;
NSString *numberChars = #"0123456789";
// the number formatter will only be instantiated once ...
static NSNumberFormatter *numberFormatter;
if (!numberFormatter)
{
[numberFormatter setLocale:[NSLocale currentLocale]];
numberFormatter = [[NSNumberFormatter alloc] init];
numberFormatter.numberStyle = NSNumberFormatterCurrencyStyle;
numberFormatter.maximumFractionDigits = 10;
numberFormatter.minimumFractionDigits = 0;
numberFormatter.decimalSeparator = decimalSeperator;
numberFormatter.usesGroupingSeparator = NO;
}
// create a character set of valid chars (numbers and optionally a decimal sign) ...
NSRange decimalRange = [text rangeOfString:decimalSeperator];
BOOL isDecimalNumber = (decimalRange.location != NSNotFound);
if (isDecimalNumber)
{
charSet = [NSCharacterSet characterSetWithCharactersInString:numberChars];
}
else
{
numberChars = [numberChars stringByAppendingString:decimalSeperator];
charSet = [NSCharacterSet characterSetWithCharactersInString:numberChars];
}
// remove amy characters from the string that are not a number or decimal sign ...
NSCharacterSet *invertedCharSet = [charSet invertedSet];
NSString *trimmedString = [string stringByTrimmingCharactersInSet:invertedCharSet];
text = [text stringByReplacingCharactersInRange:range withString:trimmedString];
// whenever a decimalSeperator is entered, we'll just update the textField.
// whenever other chars are entered, we'll calculate the new number and update the textField accordingly.
if ([string isEqualToString:decimalSeperator] == YES)
{
textField.text = text;
}
else
{
NSNumber *number = [numberFormatter numberFromString:text];
if (number == nil)
{
number = [NSNumber numberWithInt:0];
}
textField.text = isDecimalNumber ? text : [numberFormatter stringFromNumber:number];
}
return NO; // we return NO because we have manually edited the textField contents.
}
The link explaining this is Re-Apply currency formatting to a UITextField on a change event
Hope this works!

Set UILabel character limit?

I have a UILabel that shows the outside temperature, the problem is, sometimes it shows it as a XX.XXº format instead of the normal XXº or XXXº format used to show temperature, is there anyway to force the label to only show the temperature without the decimals or at least force it to only be able to use 2 characters?
You can use this to eliminate the decimals:
NSString* numberString = [NSString stringWithFormat:#"%.0f", d]; // 0 means no decimals
Otherwise I believe this will work to limit the number of chars to 2:
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.usesSignificantDigits = YES;
formatter.maximumSignificantDigits = 2;
I have not really used NSNumberFormatter very much though.
NSString *temp = [galleryEntryTree objectForKey:#"description"];
if ([temp length] > 500) {
NSRange range = [temp rangeOfComposedCharacterSequencesForRange:(NSRange){0, 500}];
temp = [temp substringWithRange:range];
temp = [temp stringByAppendingString:#" …"];
}
coverView.label2.text = temp;
You may also use substring method
NSString *newformat = [NSString stringWithFormat:#"%#",[temperature substringWithRange:NSMakeRange(0,2)]];
In this case temperature is a string that you set for your label and you are only retrieving the 1st 2 digits only

Resources