Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

roeik

macrumors member
Original poster
Dec 25, 2008
80
0
Hi,

I wrote the following function using if statements.
Everything works fine except for two bugs. If ct is equal to .04, .08, 0.7, or 0.9 the function returns the value in the previous return statement. So for example, when ct is .04 it returns 0 and not 1. The same weird behavior occurs with the numbers I specified above, but works well with all the other numbers. Any suggestions?
Thanks.

- (int) sizeIndex:(float) ct
{
NSLog(@"%f", ct);
if (ct > 0 && ct < 0.04) return 0;
if (ct >= 0.04 && ct < .08) return 1;
if (ct >= 0.08 && ct < .15) return 2;
if (ct >= 0.15 && ct < .18) return 3;
if (ct >= 0.18 && ct < .23) return 4;
if (ct >= 0.23 && ct < .3) return 5;
if (ct >= 0.3 && ct < .4) return 6;
if (ct >= 0.4 && ct < .5) return 7;
if (ct >= 0.5 && ct < .7) return 8;
if (ct >= 0.7 && ct < .9) return 9;
if (ct >= 0.9 && ct < 1) return 10;
if (ct >= 1 && ct < 1.5) return 11;
if (ct >= 1.5 && ct < 2) return 12;
if (ct >= 2 && ct < 3) return 13;
if (ct >= 3 && ct < 4) return 14;
if (ct >= 4 && ct < 5) return 15;
if (ct >= 5 && ct < 10) return 16;
if (ct >= 10) return 17;
else return -1;
}
 

Allanist

macrumors newbie
Mar 18, 2007
25
0
You're mixing floats and doubles.
Code:
float f = 0.04;
double d = 0.04;
if (f==d) {
  //This is never true
}
Code:
if (ct > 0 && ct < 0.04[B]f[/B]) return 0;
if (ct >= 0.04f && ct < .08f) return 1;
...
 

toddburch

macrumors 6502a
Dec 4, 2006
748
0
Katy, Texas
Note that your logic is a bit verbose. This is a simplified version that gives you the same functionality, but less code.

Code:
- (int) sizeIndex: (float) ct {
	NSLog(@"%f", ct);
	if (ct > 0 && ct < 0.04) return 0;
	if (ct < .08)  return 1;
	if (ct < .15)  return 2;
	if (ct < .18)  return 3;
	if (ct < .23)  return 4;
	if (ct < .3)   return 5;
	if (ct < .4)   return 6;
	if (ct < .5)   return 7;
	if (ct < .7)   return 8;
	if (ct < .9)   return 9;
	if (ct < 1.0)  return 10;
	if (ct < 1.5)  return 11;
	if (ct < 2.0)  return 12;
	if (ct < 3.0)  return 13;
	if (ct < 4.0)  return 14;
	if (ct < 5.0)  return 15;
	if (ct < 10.0) return 16;
	if (ct >= 10)  return 17;
	return -1;
}
 

blueillusion

macrumors member
Aug 18, 2008
56
3
if you are going to use comparison operators with floats and doubles, consider setting a threshold.
 

savar

macrumors 68000
Jun 6, 2003
1,950
0
District of Columbia
You're mixing floats and doubles.
Code:
float f = 0.04;
double d = 0.04;
if (f==d) {
  //This is never true
}

This is true, but misleading. You can compare floats and doubles. It's not the type that matters, its the content of the variable. Consider the following:
Code:
/Users/mehaase $ cat test.c
#import <stdio.h>

int main(int argc, char *argv) {
  float f=.25;
  double d=.25;
  if (f==d)
    printf("equal\n");
  else
    printf("not equal\n");
}

/Users/mehaase $ gcc test.c -o test
/Users/mehaase $ ./test
equal

Your example doesn't work because the number you picked (.4) is a repeating number when converted to binary representation. Because it repeats infinitely, the differing precision of float and double result in slightly different floating point numbers. (As an example, is 1/3 == .333 or is 1/3 == .333333?)

In my example, .25 is a very simple fraction when represented in binary (1/2, 1/4, 1/8 are all simple fractions in binary because the denominator is a power of two). Therefore, the differences in precision between float and double don't make a difference.

To the OP: if you're a CS student or a professional developer, you really need to learn this stuff. If you're just a hobbyist, then just keep in mind that floating point numbers are trickier than they seem and avoid them when possible.
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
Posting from my phone, so no links, but google "machine delta", and use it. This is essentially what savar and blueillusion were indicating. Since machines use a different number system than we are used to using to express things, methods of approximation had to be developed. IEEE-734 is the method that is most commonly used. Essentially, every mathmatical operation you perform on a float accumulates errors, which can eventually cause significant errors. This is obviously worse with 32-bit floating point numbers than 64-bit, simply because of lower possible precision.

You're dealing with very few significant digits. You may be able to just deal with integers that are 100x larger than the real values you are dealing with.

Good luck!

-Lee
 

Allanist

macrumors newbie
Mar 18, 2007
25
0
This is true, but misleading. You can compare floats and doubles. It's not the type that matters, its the content of the variable...
I never said they can't be compared, I was just showing a case where OP's logic fails, without diving too deep into theory. But I agree my example was misleading.
And I think your "1/3 example" is a good way of explaining the reason behind this "anomaly".
 

lazydog

macrumors 6502a
Sep 3, 2005
709
6
Cramlington, UK
This is a subtle point but worth pointing out I think. In expressions containing mixed precision, the compiler always promotes the lower precision values to the higher precision type. So, when evaluating the if statement expression:-

Code:
if (ct > 0 && ct < 0.04)

ct is first promoted to a double value and then compared to the (double) value 0.04. If the compiler took the alternative approach to resolving such cases, ie de-promote 0.04 to a float, then all would have been fine in the original code.

b e n
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.