How to avoid rounding off the float value when called from sqlite - ios

I am using the following statement to get a float value from table:
NSNumber *f = [NSNumber numberWithDouble:(double)sqlite3_column_double(statement, 0)];
The value in the database is 23.679999999 but I am getting 23.68. I tried numberWithFloat but i got the same result.
Can anyone tell me how to get the value without rounding off?

NSNumber-wrapped-double is not a suitable data type for storing decimal values when all digits must be preserved exactly. Use NSDecimalNumber instead:
unsigned char *c = sqlite3_column_text(statement, 0);
NSNumber *f = nil;
if (c) {
NSString *numStr = [NSString stringWithUTF8String:c];
f = [NSDecimalNumber decimalNumberWithString:numStr];
}
This should preserve all significant digits available in your text representation, as long as you use the native value. Converting to float or double may result in rounding due to differences in representation.

Related

NSDictionary with float value return wrong conversion

I have NSDictionary with floating values, I am trying to get values like this
[[NSDictionary valueForKey:#"some_value"] floatValue];
but looks like value not rounded correctly.
For example:
I have value in dictionary: #"0.35" but after above conversion returns 0.34999999403953552 float value, #"0.15" converts into 0.15000000596046448 etc.
When you are converting value from string to float, it lost its precision so you have to format it again. Please look at below the question you will get the better idea of that.
Make a float only show two decimal places
Converting Dictionary value to float
NSString *str = [dict objectForKey:#"key"];
CGFloat strFloat = (CGFloat)[str floatValue];
Try this code, It will work for you. Tested!
float myFloatValue= 2345.678990;
NSString* formattedNumber = [NSString stringWithFormat:#"%.02f", myFloatValue];
NSLog(#"Changed Float Value:%#",formattedNumber);

XCode not using decimal number, only using whole digit

I am trying to multiply three TextField's values which are in numbers. These values can contains decimal places. In multiplication Objective-C does not consider decimal places. For example, if the number was 3.45, it would only multiply by 3 and not with the decimals as well. Might be a basic question but i am stuck and really need help!
Here's the code i'm using so far:
- (IBAction)CalculateSimple:(id)sender {
int sum = [[principal text] intValue] * [[rate text] intValue] * [[loan text] intValue];;
total.text = [NSString stringWithFormat:#"$%d", sum]; }
Use double instead of int:
double sum = [[principal text] doubleValue] *
[[rate text] doubleValue] *
[[loan text] doubleValue];
total.text = [NSString stringWithFormat:#"$%f", sum];
You are using intValue (which returns integer type, thus your calculations are done on integers). You need to use floatValue or doubleValue (depending on your needs).
Also - check int/float/double types, if you don't know them yet.
You transform each of your operands to an intValue. Furthermore your result is also declared as an int variable.
Variables of type int can only store whole numbers.
If you want to work with floating point numbers use an appropriate data type like float or double depending on your desired precision and the size of the value.
Take the documentation on values in Objective-C as a reference.
When you are printing your result you also have to match the placeholder to the data type.
See the String Programming Guide
So with that in mind your method would look like this:
- (IBAction)CalculateSimple:(id)sender {
float sum = [[principal text] floatValue] * [[rate text] floatValue] * [[loan text] floatValue];
total.text = [NSString stringWithFormat:#"$%f", sum];
}

Convert long NSString to NSNumber

I am unable to reliably convert longer NSString to NSNumber. Specifically, I am converting MPMediaEntityPropertyPersistentID as a string to a NSNumber Sometimes it works, usually it doesn't.
Conversion code:
NSString *keke = [jsonArray objectForKey:#"next"];
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber *persistentIDasNumber = [f numberFromString:keke];
Here is an example of a successful string to number conversion:
String: 3813955856659208324
Number: 3813955856659208324
And here is an unsuccessful conversion:
String: 12790162104953153719
Number:1.279016210495315e+19
It's close but what is happening at the end? Is it too large?
Apparently the largest integer number that can be processed with NSNumberFormatter is long long, which is 9223372036854775807. Anything beyond that will lose precision and not come out as you put it in.
Instead use NSDecimalNumber, a concrete subclass of NSNumber. And it can even parse strings itself:
NSDecimalNumber *dn=[[NSDecimalNumber alloc]initWithString:#"12790162104953153719"];
NSLog(#"dn: %#",dn);
NSDecimalNumber can handle up to 38 digit long decimal numbers before it loses precision.
This is how you do it:
unsigned long long number = [[jsonArray objectForKey:#"next"] longLongValue];
NSNumber * numberValue = [NSNumber numberWithUnsignedLongLong:number];

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];

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