NSNumber numberFromString not placed decimals - ios

I am trying to convert NSString to NSNumber and it seems to create a decimal point issue here.
NSString *str = #"515.51515";
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber * myNumber = [f numberFromString:str];
NSLog(#"Number here:%#",myNumber);
[f release];
& result print is
2015-03-01 08:09:28.353 myApp [57376:2086924] Number here: 515.5151499999999
Actual debug log picture here
but actually it should be 515.51515 rather 515.5151499999999.
I tried all comibination with f.usesSignificantDigits & f.maximumFractionDigits =10 but no luck.
please let me know How to fix this?

RMaddy is correct, floating point numbers will be a bit off.
Since an NSDecimalNumber is an NSNumber you can use:
NSNumber *number = [NSDecimalNumber decimalNumberWithString:#"515.51515"];

Try to use construction:
NSNumber *myNumber = [NSNumber numberWithFloat:[str floatValue]];
I think it should work correctly.

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

NSArray change type of NSNumber

I want to store some NSNumber as double in a NSArray. So I tried that :
NSArray *diamArray = [[NSArray alloc] initWithObjects:
[NSNumber numberWithDouble:1.0],
[NSNumber numberWithDouble:1.2],
nil];
And then, I ask Xcode to show the diamArray:
NSLog(#"%#", diamArray);
And here is the result:
[8873:1153347] (
1,
"1.2"
)
So we can see that both numbers are not treated the same way. It's a problem for me as these values are usable as their type changes. Specially, in the debug watch of the array, I can see the decimal number (1.2) as "double" but the 1.0 value is shown as "null".
How can I force the array to consider 1.0 as a double ?
It can be confusing to decipher data types from NSLog as it is attempting to display convenient information. In this case, 1.0 is exactly one, so it is truncating that value so that it appears to be an Int. I'll almost guarantee that if you were to pull the item out of the array and display it's objCType you'd find that it's a double:
NSLog("%#: %s", diamArray[0], [diamArray[0] objCType]);
The other thing to consider is that values can be cast coming out of NSNumber, so even if it stores 1.0 as an integer value, you can still extract it as a double:
[diamArray[0] doubleValue]
NSNumber is a class cluster. You should not worry about how it store the information, but you should instead mostly care about how you retrieve that information.
To get back your double, you have just to do:
double myDouble = [dimArray[0] doubleValue];
but there are also:
[dimArray[0] intValue];
[dimArray[0] integerValue];
[dimArray[0] unsignedIntegerValue];
[dimArray[0] floatValue];
...
Thanks for your info and suggestions.
I find out that it's related to locale. My default locale is fr_FR and then I tried that:
NSNumberFormatter *f = [[NSNumberFormatter alloc] init];
f.numberStyle = NSNumberFormatterDecimalStyle;
NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US"];
[f setLocale:usLocale];
NSArray *pasArray = [[NSArray alloc] initWithObjects:
[f numberFromString:[[NSNumber numberWithDouble:1.0] stringValue]],
[f numberFromString:[[NSNumber numberWithDouble:0.25] stringValue]],
nil];
and it works as expected. I guess that, due to locale difference, the dot is misinterpreted. But I think it's not really clean to do so.
My conclusion is that David Berry is right: I don't have to care about the display and rather ask for the format I need when I need it.
Thanks again to help me to understand why it wasn't a problem.

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.

Converting double to string return strange value in objective c

I have an NSDictionary which consist of multiple key/pair values. One of them consist double value.
NSNumber *goalValue = [info objectForKey:#"goalValue"];
I put breakpoint and I found that goalValue store the normal value that I need.
and just below I convert it to NSSting like
NSString *stringValue=[goalValue stringValue];
and this stringValue store very strange value.
Guys please help me. I am totally puzzled, I did goggle but nothing change. Please help me. Thanks in advance.
The method stringValue will convert the NSNumber to string by internally calling descriptionWithLocale: with locale as nil and this method in turn will call initWithFormat:locale:,
From Apple docs,
To obtain the string representation, this method invokes NSString’s initWithFormat:locale: method, supplying the format based on the type the NSNumber object was created with:
So format specifier used for double is %0.16g(i.e. 16 digit precision) hence the value 98.09999999999999
I'd suggest using NSNumberFormatter,
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
[numberFormatter setMaximumFractionDigits:2]; //2 decimal places, change this as required.
NSString *string = [numberFormatter stringFromNumber:goalValue];
Hope that helps!
To prevent this behavior, I suggest using NSDecimalNumber (also this is from my experience best format when dealing with very precise amounts)
NSDecimalNumber *doubleDecimal = [[NSDecimalNumber alloc] initWithDouble:[info objectForKey:#"goalValue"]];
for two digits formatting, use numberFormatter
NSNumberFormatter * nf = [[NSNumberFormatter alloc] init];
[nf setMinimumFractionDigits:2];
[nf setMaximumFractionDigits:2];
NSString *stringValue = [nf stringFromNumber:doubleDecimal]
Its showing the rounded value so you can round the value to single digit using NSNumberFormatter.
NSNumberFormatter *fomatter = [[NSNumberFormatter alloc] init];
[fomatter setMaximumSignificantDigits:2];
NSString *stringValue=[fomatter stringFromNumber:goalValue];

NSNumber to float Value

When I convert NSNumber to float value using 'floatValue', there is a difference in precision. Example, I have a NSNumber 'myNumber' having value 2.3, and if I convert myNumber to float using 'floatValue', its value becomes, 2.29999. But I need exactly 2.30000. There is no problem with number of zeros after 2.3, I need '2.3' instead of '2.9'.
How can I do so?
I had similar situation where I was reading value and assigning it back to float variable again.
My Problem statement:
NSString *value = #"553637.90";
NSNumber *num = #([value floatValue]); // 1. This is the problem. num is set to 553637.875000
NSNumberFormatter *decimalStyleFormatter = [[NSNumberFormatter alloc] init];
[decimalStyleFormatter setMaximumFractionDigits:2];
NSString *resultString = [decimalStyleFormatter stringFromNumber:num]; // 2. string is assigned with rounded value like 553637.88
float originalValue = [resultString floatValue]; // 3. Hence, originalValue turns out to be 553637.88 which wrong.
Following worked for me after changing lines:
NSNumber *num = #([value doubleValue]); // 4. doubleValue preserves value 553637.9
double originalvalue = [resultString doubleValue]; // 5. While reading back, assign to variable of type double, in this case 'originalValue'
I hope this would be helpful. :)
If you need exact precision, don't use float. Use a double if you need better precision. That still won't be exact. You could multiply myNumber by 10, convert to an unsigned int and perform your arithmetic on it, convert back to a float or double and divide by 10 and the end result might be more precise. If none of these are sufficiently precise, you might want to look into an arbitrary precision arithmetic library such as GNU MP Bignum.
I've done the following but it is showing me correctly
NSNumber *num = [NSNumber numberWithFloat:2.3];
float f = [num floatValue];
NSLog(#"%f", f);
You can play with something like this:
float x = 2.3f;
NSNumber *n = [NSNumber numberWithFloat:x];
NSNumberFormatter *fmt = [[NSNumberFormatter alloc] init];
[fmt setPositiveFormat:#"0.#"];
NSString *s = [fmt stringFromNumber:n];
float f = [s floatValue];

Resources