Advertisements

Floating in Uncertainty


Among the primitive data types that Objective-C offers are float and double. Similar to long, double is simply double the storage in bits of float. However, as the name suggests, both are floating-point numbers. That is, the decimal point literally “floats” around as necessary. This can lead to many subtle bugs, even between executions of the same program.

How Do They Work?

Both types have a certain numbers of bits for storage. The exact number of bits varies per implementation, just as the exact storage sizes for ints and doubles aren’t fixed. However, a floating point number effectively has two parts, the “whole” part and the “fractional” part. The floating nature comes in because the number of bits used to store each section is not always the same, and will vary depending on the sizes of the numbers involved.

The Precise Issue

Although there are an infinite number of integers, they all differ by the same amount—1. Therefore it is relatively easy to represent an integer value as bits. By contrast, however, the difference between one decimal number and another is incredibly small, and, what’s worse, this difference can change. When trying to squeeze an infinite number of digits with infinite precision into a finite number of bits, something has to give. This usually means that the floating-point value is rounded, and is not completely accurate. Here’s a simple program (using plain C) to illustrate this issue:

int main (int argc, const char *argv[]) {
	float f = 1234.123456789;
	printf("%f\n", f);
	printf("%.9f\n", f);
	return 0;
}

Output:

1234.123413
1234.123413086

The first print statement (printf() is nearly identical to NSLog(), except that it takes C-style strings instead) shows the actual value of f in memory, with ten digits in this case. Notice that the value is different from the value we assigned to the variable. This is because there are not enough bits to hold every single digit, so some of it had to be rounded away. That rounding is not perfectly accurate—it rounds the tailing ‘456789’ into ‘413’. If, however, we try to force it to display nine digits as seen in the next line, we still end up with the ‘413’, along with a tailing ‘086’—not digits that we put in.

Comparisons

How many times should this loop run?

#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]){
	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
	int count = 0;
	for (float i = 10; i != 0; i -= 0.1) {
		count++;
		printf("count is %d\n", count);
	}
	[pool drain];
    return 0;
}

Common sense tells us that it should run 100 times, but in fact this is an infinite loop. Because of these rounding errors, i will never be exactly equal to zero. It’ll come close after 100 cycles through, but it won’t be perfect. As such, when dealing with floating point numbers, you want to check to see if it’s close to a value. In the above example, the comparison should be i >= 0; (the equal bit because the floating point number might be a tiny negative value) to ensure that the loop ends.

To check if two floating point numbers are equal, you could use the == (double equals) operator, but there’s no guarantee that they will give an accurate result, especially after many calculations. A better way (albeit less efficient) would be to get the absolute value of their difference, and see if it’s less than a small number, such as 0.00001. If it’s less, you can safely assume they’re equal; otherwise, they’re not.

Floating point inaccuracies can be very difficult to debug, so it pays off to take precautions earlier. As a matter of fact, I spent about half an hour trying to figure out why something wasn’t showing up on screen, when in fact a botched conversion from integers to floating point (similar issues result) lead to everything being 0. Not fun.

Advertisements
Leave a comment

1 Comment

  1. 80387 Microprocessor (The 387), Floating-Point « Jeinrev

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Advertisements
  • Welcome

    My goal is to make CupsOfCocoa into a beautiful source for beginners to the iPhone platform to get started. Subscribe below for more, and stay tuned!

  • Contact Me

    If you need to contact me for any reason, feel free to send me an email.
  • The Giving Spirit

    If you've found this site helpful, would you consider donating a little sum? Any amount is appreciated...Thanks so much!

  • Roadmap

  • Enter your email address to follow this blog and receive notifications of new posts by email.

    Join 222 other followers

  • Back to the Past

    July 2011
    S M T W T F S
    « Jun   Aug »
     12
    3456789
    10111213141516
    17181920212223
    24252627282930
    31  
  • Time Machine

  • You count!

    • 621,851 views
  • Worldwide Stats

    free counters
  • Advertisements
%d bloggers like this: