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.
Related
I'm a newbie in XCode programming. I have following code:
CGSize firstSize = CGSizeMake(1.0,1.0);
NSLog(#"[height] %#", firstSize.height);
//...
At runtime, I got the result:
height (null)
Could someone help me to explain while that code print null for firstSize.height?
Many thanks
Use %f instead of %# :
CGSize firstSize = CGSizeMake(1.0,1.0);
NSLog(#"[height] %f", firstSize.height);
%# is used for all objects, here you are dealing with Core its float type, you need to use %f for float.
If you want decimal precision as well, use %.2f for 2 decimal digits.
You can also use this nice function
NSString * NSStringFromCGSize (
CGSize size
);
defined by UIKit in UIGeometry.h (together with many other useful functions):
NSLog(#"Size: %#",NSStringFromCGSize(firstSize));
Maybe this is a dumb question, but I really can't get it. For some reason float values in my program get rounded up during the assignment statement.
Here is the code:
Float64 time,test;
for( Shot *sh in _arrayOfShots)
{
time = sh.bFrameTime;
// right here time variable gets value rounded up to 2 decimal places
// for example: if sh.bFrameTime = 81.919998 => time = 81.92
NSNumber *num = [NSNumber numberWithFloat:time];
test = [num floatValue];
[edgeTime addObject:num];
}
// this is my Shot object structure
#interface Shot : NSObject
{
int bFrame;
int eFrame;
Float64 bFrameTime;
}
If anyone knows how to deal with this, please give me hint!
Thank you!
81.919998 => time = 81.92
is not "rounded up to two decimal places". The difference in the two is 0.000002, a change in magnitude of 0.0000000244, or about 8 decimal places. If your source value is single-precision float then it only has 7 decimal places of accuracy. (But you didn't show the declaration of that so we can't tell.)
The difference could also have to do with how you displayed the two values, as NSLog does a modicum of rounding.
Add an if statement where you check if the rounded number is larger than the initial number, if so subtract it by 1
I am probably missing something obvious (still learning about Objective-C!) but for some reason one of my NSString variables has a null value in my if statement and I don't know why?
I have even output to NSLog and I still can't see why it's behaving like this.
Basically, the user enters an amount in a text field (itemWeight) and this if statement validates the input and displays an alert according to the result. The problem only seems to be when 0.751 is entered, if you enter any other amount (0.750, 0.749, 0.752, 0.753 and so on) it works as expected.
Relevant code samples as follows...
.h file:
#property (strong, nonatomic) IBOutlet UITextField *itemWeight;
.m file:
NSString *rawWeightText = itemWeight.text;
float convertedWeightText = rawWeightText.floatValue;
NSString *weightMessage;
if (convertedWeightText <= 0.750)
{
weightMessage = #"under 0.750";
}
else if (convertedWeightText >= 0.751)
{
weightMessage = #"0.751 or over";
}
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle: #"Error"
message: weightMessage
delegate: nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
Any ideas where I'm going wrong/what I've forgotten to do would be much appreciated, thank you!
Looking at the condition of your if-else if code does not have the range of from 0.750 to 0.751.
floating-point values must be careful to compare. you should consider about 0.751 possibility 0.75099999...
the following loop, the result is 99.999046, not 100. Continue to add more accuracy is poor.
float a= 0.1f;
float result = 0.f;
for(int i = 0; i<1000; i++)
{
result += 0.1f;
}
printf("result:%f", result); //99.999046
So, In General, Comparison of these expressions is not recommended.
if (result == expectedResult)
Writing the following method is recommended to compare.
bool AlmostEqualRelative(float A, float B, float maxRelativeError)
{
if (A == B)
return true;
float relativeError = fabs((A - B) / B);
if (relativeError <= maxRelativeError)
return true;
return false;
}
For more information, please read here
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
also, you must read this wiki:
http://en.wikipedia.org/wiki/Floating_point
http://en.wikipedia.org/wiki/Denormal_number
Decimal values often can't be exactly represented in binary. When the user enters 0.751, its likely that the actual float that you get back is slightly smaller, like 0.750999942. Try logging the value to see what's going on.
You are not the first programmer who is surprised by the actual behavior of floating point numbers.
In fact it is more a problem with binary decimal numbers, then the floating point details.
Try to convert 0.751, which has only 3 digits in the fractional part, into a binary number and you'll see.
To make it short, 0.751 is represented as a binary exponent of -1 and a mantissa of 1.10000000100000110001001 in a float (float only has 23+1 bits of precision for the mantissa).
That is, in decimal, an exponent of -1 and a mantissa of 1.5019999742507935.
Therefore 2^-1 * 1.5019999742507935 = 0.7509999871254 and it does not pass the test in the if.
I am new to iOS programming/objective c, I am trying to do an iterative trial and error calculation and I am stuck. Ordinarily this code would have worked in excel VBA so I'm not sure how to overcome this issue in obj C:
- (IBAction)calculate:(id)sender {
static float friction=2;
static float difference;
float Re = [pipe_id.text floatValue] * [fluid_velocity.text floatValue] / [kin_viscosity.text floatValue];
ReynoldsNo.text = [[NSString alloc]initWithFormat:#"%6.2f", Re];
do{
float Colebrook1 = 1/powf(friction,0.5);
float Colebrook2 = -2*log10f([RelativeRoughness.text floatValue]/(3.7*[pipe_id.text floatValue]) + 2.51/(Re*powf(friction,0.5)));
float difference = fabsf((Colebrook1-Colebrook2)*1000);
friction = friction - 0.000001;
FrictionFactor.text = [[NSString alloc]initWithFormat:#"%6.2f", friction];
Cole1.text = [[NSString alloc]initWithFormat:#"%6.2f", Colebrook1];
Cole2.text = [[NSString alloc]initWithFormat:#"%6.2f", Colebrook2];
}while (difference > 0.000001);
}
So when I compile this, the value for friction stays at 2. My loop isn't working, so the whole trial and error thing has fallen apart. I need some help to see how this should be written in objective C. Thanks for you help, ALM.
This line is your problem:
float difference = fabsf((Colebrook1-Colebrook2)*1000);
You already declare the variable difference outside the loop; there is no need to declare it again inside the loop.
You probably want to say:
difference = fabsf((Colebrook1-Colebrook2)*1000);
Also, are you sure that your outer declaration needs to be static? That means its value persists between calls to the method. It's valid code, but unusual to see.
Be aware of block scope. Your inner difference shadows the outer, so you may want to avoid re-declaring it by simply removing the float.
Also, as a convention tip, leave the capitalized identifiers for classes.
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.