Accurately Converting NSString to GLFloat - iPhone - iphone

Say I have some vertice values which I am reading into my app as a NSString :
-7501.6 -6198.2 834.939 -5547.66 -6348.32 2122.65
The values in the source are always 6 figures in length.
I need to pass these exact values to OpenGL. If I try to cast as a float (using NSString floatValue) then, as expected, I get an approximate value for each float due to the inexact nature of a float :
-7501.600098, -6198.200195, 834.939026 -5547.660156, -6348.319824, 2122.649902
Can anyone suggest a way that I can get these values into OpenGL and retain their exact initial integrity ?
Thank you.

maybe this: NSString to NSNumber could help.

See 'Getting Numeric Values' paragraph from NSString Documentation (Apple).
[str floatValue];
[str doubleValue];

Related

How to convert NSDecimalNumber to CLLocationDegrees without losing precision?

I need to convert NSDecimalNumber with lat/lon values which I need to convert to CLLocationDegrees. I used -[NSDecimalNumber doubleValue] method. But the value loses its precision. I want the values to be same. The following is what I am talking about(I hope everyone would be aware about this issue already).
NSString *coordStr = #"-33.890934125621094";
NSDecimalNumber *lat = [NSDecimalNumber decimalNumberWithString:coordStr];
NSLog(#"%#", lat); // -33.890934125621094
NSLog(#"%lf", [lat doubleValue]); // -33.890934
Is there any way that I should do instead of doing the above?
Try out to convert the String with the doubleValue method
NSString *coordStr = #"-33.890934125621094";
NSLog(#"%.17g",coordStr.doubleValue); //-33.890934125621094
Check out this post: How to print a double with full precision on iOS?
edit:
the docu says: typedef double CLLocationDegrees; so you can double test = coordStr.doubleValue; the problem is only, that NSLog doesn't print the complete value. but instead the double var saves the complete value.
CLLocationDegree is a double. So the maximum precision can only equal that of a double datatype.

Why isn't the NSNumber class correctly converting my NSString object to a long long?

I'm trying to convert an NSString object to an NSNumber with the same numerical value. When I create the NSString object using this statement...
NSString *songID = [localNotif.userInfo objectForKey:#"SongID"];
the var songID contains the string value #"10359537395704663785". and when I attempt to convert it to an NSNumber object using the statement...
NSNumber *songIDNumber = [NSNumber numberWithLongLong:[songID longLongValue]];
the var songIDNumber contains the wrong value of 9223372036854775807
What am I doing wrong? It might also be worth noting that sometimes this code does work and produce the correct NSNumber value, but most of the time it fails as shown above.
Thanks in advance for your help!
UPDATE: God I love this site! Thanks to unbeli and carl, I was able to fix it using the updated code for converting from the NSString to the NSNumber...
unsigned long long ullvalue = strtoull([songID UTF8String], NULL, 0);
NSNumber *songIDNumber = [NSNumber numberWithUnsignedLongLong:ullvalue];
longLongValue returns LLONG_MAX in case of overflow, and LLONG_MAX is exactly what you get, 9223372036854775807. You value simply does not fit in long long
Try using NSDecimalNumber instead.
9223372036854775807 decimal is 0x7FFFFFFFFFFFFFFF in hex. Your number is 10359537395704663785, which is too large for a long long and overflows. From the NSString documentation:
Returns LLONG_MAX or LLONG_MIN on overflow.

What is the fastest routine to convert NSArrays to C-style (double) arrays?

I have 2 NSArray (Mutable, actually) that I am trying to convert to a C-style double array for a c routine i am passing them to.
Here is my Objective-C routine:
NSMutableDictionary *childDictionary = [myParentDictionary objectForKey:resort_code];
latitudeArray = [childDictionary objectForKey:#"lat"];
longitudeArray = [childDictionary objectForKey:#"lon"];
int nvert = [latitudeArray count];
double laArray[nvert];
double loArray[nvert];
for(int i=0; i<nvert; i++) {
double dLat = [[latitudeArray objectAtIndex:i]doubleValue];
double dLon = [[longitudeArray objectAtIndex:i]doubleValue];
laArray[i] = dLat;
loArray[i] = dLon;
}
This takes upwards of 3-8 seconds on the 3G iPhone (instantaneous on the simulator -- yet another reason to test on the device )
is there faster way? I have to end up with laArray[i] and loArray[i] as c-style arrays of doubles.
(to expand on the question for the benefit of a commenter):
Each array consists of #"38.448745" (lat) and #"-122.9847684" (lon) style content. I do this cos to be pushed onto an NSArray, the lat and lon need to be objects. I simply used:
[latitudeArray addObject:[NSString stringWithFormat: #"%.10f",dlat]];
[longitudeArray addObject:[NSString stringWithFormat: #"%.10f",dlon]];
I suppose I could change that to:
[latitudeArray addObject:[NSNumber numberWithDouble: #"%.10f",dlat]];
[longitudeArray addObject:[NSNumber numberWithDouble: #"%.10f",dlon]];
...which may reduce the conversion time of
double dLat = [[latitudeArray objectAtIndex:i]doubleValue];
but wouldn't I still need that exact line to convert from NSString to double? It just may work faster?
thx
dlat is a double, right?
So instead of:
[latitudeArray addObject:[NSString stringWithFormat: #"%.10f",dlat]];
Do:
[latitudeArray addObject:[NSNumber numberWithDouble:dlat]];
They both respond to doubleValue but the NSNumber should not have to do any string parsing since it's stored as a numeric value already. And you never have to go to a string at all.
I suspect you have an array of strings like #"213.12385" that need to be parsed and converted when you call doubleValue on them. If that is where the issue is, the C arrays have nothing to with this.
Only thing I would add here is to throw Shark on this and see where it's spending it's time. If it's spending time in doubleValue find a different way to parse the strings with preprocessing in background or something. If it's in objectAtIndex: perhaps fast enumeration would help. If it's somewhere else entirely then you know it's not this snippet that's slow.
For the general case of converting an NSArray to a C array, you can use getObjects:. In this case, though, want you actually want is not to convert the NSArray, but to derive an array of doubles from an NSArray of some unspecified object type.
One obvious way to speed things up would be fast enumeration rather than sending a message to get the object for each iteration of the loop. I suspect the real solution, though, is outside your algorithm. The slowness probably comes from transforming whatever objects the array contains into doubles, in which case you'll need to find a way around that — maybe store doubles all along, maybe do the conversion in the background, etc. If you're creating the arrays yourself and there isn't some compelling reason for the objects to be strings, you should use NSNumbers instead. Those should be quite a bit faster.
The best solution is probably to make sure those values never end up in an NSArray as NSString values. I would attack this at the source.
So you edited your question and added that you are actually building those arrays. So why not use native arrays of doubles or floats from the start? I usually recommend against this but in your case it sounds like there is a huge performance gain.
Possibly using fast iteration, but I doubt that will really speed up your loop.

objective-c converting strings to usable numbers

I have strings that look about like this:
stringA = #"29.88";
stringB = #"2564";
stringC = #"12";
stringD = #"-2";
what is the best way to convert them so they can all be used in the same mathmatical formula?? that includes add, subtract.multiply,divide etc
Probably floatValue (as it appears you want floating-point values), though integerValue may also be of use (both are instance methods of NSString).
[stringA doubleValue]
These are all wrong, because they don't handle errors well. You really want an NSNumberFormatter.
If you have the string #"abc" and try to use intValue or floatValue on it, you'll get 0.0, which is obviously incorrect. If you parse it with an NSNumberFormatter, you'll get nil, which is very easy to distinguish from an NSNumber (which is what would be returned if it was able to parse a number).
Assuming that you have NSString variables.
NSString *stringA = #"29.88";
NSString *stringB = #"2564";
NSString *stringC = #"12";
NSString *stringD = #"-2";
suppose, you want to convert a string value to float value, use following statement.
float x=[stringA floatValue];
suppose, you want to convert a string value to integer value, use following statement.
NSInteger y = [stringC intValue];
Hope, it helps to you.

Proper Usage and Formatting of a Float in Objective-C (or C)

I have an iPhone app. I am storing a float value, (distance), in my sqlite3 db. (The field in the db is formatted to float) I am able to store float values correctly in the db no problem. However, I can't seem to figure out how to pull the value back out of the db the format and present it correctly. Here is my code for pulling the value out of my db and using it:
NSString *itemDistance = [NSString stringWithFormat:#"%f",[item distance]];
float questionDistance = [itemDistance floatValue];
[item distance] is a float value. I can't get this to work. I get a REALLY long value instead. What am I doing wrong? Any help would be greatly appreciated.
Thank you in advance for your help,
L.
Assuming your -distance method is returning the right value, then this sounds like basic misunderstanding of how floats work in C. Common mistake. Every developer falls into this trap at least once.
Floating point numbers can actually only represent a fairly limited number of values. Specifically, unless you happen to choose a value that is exactly representable as a float, you'll get the nearest value, which will often have many decimal places of data.
The reason for this is because a float is only 32 bits; 4 bytes. Now, how many numbers with decimal points are there between 0..1000000 or 0..1000 or, even, 0..1. Infinite. Floats implement a very finite subset of possible numeric values and do so in a way where the resulting possible values may have many decimal places.
Consider:
printf("%5.18f\n", (float) 2.05);
printf("%5.18f\n", (float) 2.45);
printf("%5.18f\n", (float) 4200.75);
printf("%5.18f\n", (float) 37.89);
printf("%5.18f\n", (float) 1.2);
printf("%5.18f\n", (float) -1.2);
This prints:
2.049999952316284180
2.450000047683715820
4200.750000000000000000
37.889999389648437500
1.200000047683715820
-1.200000047683715820
Those values are as close to the values in the bit of code that a float could represent.
If you need more precision, use a double. More precision than that? Use NSDecimalNumber.
And, if you can, use CoreData. It makes managing this kind of thing a bit more straightforward.
why go round in circles?
NSString *itemDistance = [NSString stringWithFormat:#"%.2f",[item distance]];
float questionDistance = [itemDistance floatValue];
Where the .2 is saying I want 2 decimal places.
Whats the type of of distance? If it is an instance of NSNumber then I dont think the code you wrote will work, try
NSString *itemDistance = [[item distance] stringValue];
float questionDistance = [itemDistance floatValue];
or even
float q=[[item distance] floatValue];