Objective c - float returning wrong value - objective-c

I'm using objective c and trying to output a value from a function. Apparently I am doing something wrong because I'm receiving an incorrect value.
This is my code:
-(float) getAngleBetween {
float num = 0.0;
return num;
}
and I'm calling it as follows:
float *theAngleBetween = [self getAngleBetween];
NSLog(#"Angle.. = %f", theAngleBetween);
Any help please?

float theAngleBetween = [self getAngleBetween];
// ^
There should be no *.
Since you are returning a float, the receiver should have type float as well. float* means a pointer to float, which is entirely different from float.
BTW, make sure you declare -(float)getAngleBetween; before you call [self getAngleBetween]. Put it in the #interface. If it is not declared before, the method will be assumed to have the type -(id)getAngleBetween;. On x86 returning a id and a float use different API (objc_msgSend vs objc_msgSend_fpret), which may be the cause of wrong result.

You should have:
float theAngleBetween = [self getAngleBetween];
Get rid of the *, that's for objects only, float is a primitive data type.

Related

Incompatible block pointer type initializing float

Im not sure how to get this to work: I was thinking something to do with typedef, but I can't find much on the subject.
float (^pixelsToDistance)(float, float, NSString *) = ^(float distance, float scale, NSString *conversion)
{
// Code goes here
}
Im trying to return a float value from this block function.
Should I use a function instead?
You were close. You want:
float (^pixelsToDistance)(float, float, NSString *) = ^float(float distance, float scale, NSString *conversion) { ... };
Note the return type after the ^ on the right hand side of the assignment operator.
As the commentator points out, you can omit the return type if it's clear to the compiler what you're returning from the block. E.g.:
float (^pixelsToDistance)(float, float, NSString *) = ^(float distance, float scale, NSString *conversion) { return 0.0f };

Simple division not happening

I'm trying to calculate the appropriate height for a UITableViewCell and a UIImageView by using the following method that gets called:
-(void)ratioCalculator
{
picH = image.size.height;
picW = image.size.width;
NSLog(#"%d = width %d = height", picW, picH);
picRatio = (picW/picH);
NSLog(#"%F", picRatio);
imageViewH = (260/picRatio);
NSLog(#"%d int", imageViewH);
return;
}
The thing is, when it gets called, the picRatio = (picW/picH); doesn't seem to be happening as the console says this:
2012-11-18 21:56:48.787 Name[5374:c07] 640 = width 360 = height
2012-11-18 21:56:48.788 Name[5374:c07] 1.000000
2012-11-18 21:56:48.788 Name[5374:c07] 260 int
The 1.000000 is the float picRatio and the 260 is the imageViewH. Obviously this means the incorrect heights are used for both the UITableViewCell and the UIImageView which are calculated like this:
else {
[self ratioCalculator];
return (imageViewH + 20);
}
and
- (void)showImage:(UIImage *)theImage
{
self.imageView.image = theImage;
self.imageView.hidden = NO;
[self ratioCalculator];
self.imageView.frame = CGRectMake(10, 10, 260, imageViewH);
self.photoLabel.hidden = YES;
}
As stupid a question as this probably is, why isn't this simple division working? Again, sorry if this is a stupid question, but it has me stumped. I feel like I'm going slightly mad.
Any help would be greatly appreciated,
Regards,
Mike
picRatio = ((float)picW/(float)picH);
Objective-c needs the proper iVar type assignment before dividing.
When you divide 2 integers, the output isn't a float, but an integer.
So 640/360 = 1.777 and this is treated as an integer, so the decimal value is ignores, which gives you the 1, you are getting.
If you do what I wrote, will actually produce a float, and give you the 1.777 output.
What you are missing is to cast the integers to float in order to make a float division
picRatio = (picW/picH); // gives an int division if picW and picH are declared integers
picRatio = (float)(picW)/picH; // gives you a floating point division
Since no one is posting an official answer, I thought I'd do so to help anyone in a similar position. The comments on my question put me on the right track, and after further investigations I discovered that the compiler calculates the output based on the types of the operands. Therefore, if all the operands are ints, it casts an int to the destination, regardless of if it's a float or not. Solution: make at least one of your operands a float.
Hope this helps anyone in a similar position.

How do I use the assignment operator *= to multiply a value by ten?

Quite simply:
current *= 10;
Returns an "invalid operands to binary *" build error.
int *current = 0;
- (void)bOnePress:(id)sender {
current *= 10;
current += 1;
[resultDisp setText:[NSString stringWithFormat: #"%i", current]];
}
Google won't tell me what I'm doing wrong, so I'm asking here. :S
Edit: ANSWERED:
int current = 0;
Remove the *.
You have declared your variable as a pointer to memory address 0, not as an integer variable that can be multiplied.
You declared a pointer to an integer, not an integer. You probably want something like
int current = 0;
Don't get confused with Objective-C manner to deal with objects. These are always pointers, but an int is just an int, it's a type by itself. You will only use a pointer to an int when you want to reference another portion in memory that contains an int.
You're multiplying the pointer by ten, not the value.
it should read:
*current *=10;
*current *= 10;

Cast an Objective C UITextField value to float

I have a UITextField called txtDiscount
It has a value in it: txtDiscount.text == 2.3 //for example
I've tried:
float test = (NSNumber *)txtDiscount.text;
And it compiles, but at runtime breaks down.
Unacceptable type of value for attribute: property = ..."; desired type = NSNumber; given type = NSCFString; value = .
How can I cast the value?
Any help greatly appreciated,
Thanks // :)
You probably want something like:
float test = [txtDiscount.text floatValue];
The NSString documentation provides a list of all the built-in casts.
A cast like this
(NSNumber *)myInstance
is telling the compiler to treat 'myInstance' as if it were an instance of class NSNumber. This may influence compile time warnings and errors. Note: - the compiler. It makes no difference to the code that is generated or run - at all. The code that you are running is still
float test = [txtDiscount text];
where the method -text is returning a pointer to an NSString and you are trying to assign it to a float variable.
see clee's answer for how to get float value from an NSString - but make sure you understand why what you were trying to do is wrong. It will help loads in the long run.

object_getInstanceVariable works for float, int, bool, but not for double?

I've got object_getInstanceVariable to work as here however it seems to only work for floats, bools and ints not doubles. I do suspect I'm doing something wrong but I've been going in circles with this.
float myFloatValue;
float someFloat = 2.123f;
object_getInstanceVariable(self, "someFloat", (void*)&myFloatValue);
works, and myFloatValue = 2.123
but when I try
double myDoubleValue;
double someDouble = 2.123f;
object_getInstanceVariable(self, "someDouble", (void*)&myDoubleValue);
I get myDoubleValue = 0. If I try to set myDoubleValue before the function eg. double myDoubleValue = 1.2f, the value is unchanged when I read it after the object_getInstanceVariable call. Setting myIntValue to some other value before the getinstancevar function above returns 2 as it should, ie. it has been changed.
then I tried
Ivar tmpIvar = object_getInstanceVariable(self, "someDouble", (void*)&myDoubleValue);
If I do ivar_getName(tmpIvar) I get "someDouble", but myDoubuleValue = 0 still! Then I try ivar_getTypeEncoding(tmpIvar) and I get "d" as it should be.
So to summarize, if typeEncoding = float, it works, if it is a double, the result is not set but it correctly reads the variable and the return value (Ivar) is also correct.
I must be doing something basic wrong that I cant see so I'd appreciate if someone could point it out.
object_getInstanceVariable is a confused little function. It is documented that the last parameter is a void ** parameter—that is, you pass the address of a void * variable and get a pointer to the instance variable—but it is implemented as if it was a void * parameter—that is, you pass the address of the variable that you want to hold a copy of the instance variable. The problem is that the implementation ignores the size of the instance variable and just does a pointer copy. So anything that's the same size as a pointer will work perfectly. If you're running on a 32-bit architecture, only the high 32 bits will be copied. (You should witness the same behavior with a long long instance variable as well.)
The solution is to use the primary API, key-value coding, using -valueForKey:.
The other solution: If you wanted to write a fixed version, say as a category for NSObject, it would look something like this:
#implementation NSObject (InstanceVariableForKey)
- (void *)instanceVariableForKey:(NSString *)aKey {
if (aKey) {
Ivar ivar = object_getInstanceVariable(self, [aKey UTF8String], NULL);
if (ivar) {
return (void *)((char *)self + ivar_getOffset(ivar));
}
}
return NULL;
}
#end
Then your code would look like this:
double myDoubleValue = *(double *)[self instanceVariableForKey:#"someDouble"];
What about using valueForKey:?
NSNumber * value = [self valueForKey:[NSString stringWithUTF8String:ivar_getName(tmpIvar)]];
NSLog(#"Double value: %f", [value doubleValue];
Note: this requires you to have a "someFloat" method. If you want to use setValue:forKey:, you'll also need the "setSomeFloat:" method. This is easily implemented by declaring the ivar as an #property and synthesizing it.