tags:

views:

74

answers:

3

I'n obj-c I have a timer fire every .1 seconds and increment a double value (seconds) by .1 So it should basically keep time counting up by tenths of a sec. When it fires it checks some if else statements to see if (seconds) is equal to 3, 9, 33 etc. but these are never triggered. I suppose it is because of the way doubles are represented in bits thats the decimal is an approximation and never actually a whole number.

How can I fix this so my statements are triggered?

-(void)timeSeconds:(NSTimer*)theTimer{
seconds = seconds+0.1;
NSLog(@"%f", seconds);
if (seconds==3.0) {
    [player pause];
    [secondsTimer invalidate];
}
else if (seconds==9){
    [player pause];
    [secondsTimer invalidate];
}
+2  A: 

Floating point math is imprecise, using floating to count is not a great idea, but if you must, check that the difference between the count and the variable is very small.

mikerobi
+1 for the *very small* part. Just like invoking `sprintf()` and making sure the buffer is *big enough* :-)
André Caron
+4  A: 

0.1 cannot be represented exactly in binary floating point, so you get a small error that accumulates over time. If you want an exact value, use an int or long variable that get incremented by 1 each time called tenthsOfSeconds.

Chris Dodd
+5  A: 

The floating point types cannot represent some numbers exactly, so when these are added, the error is compounded and the floating point type becomes less and less precise.

Use an integral type but represent the time difference using greater resolution, for example, use an NSUInteger to represent milliseconds instead of seconds, and increment by 100 instead of 0.1. Instead of comparing seconds == 3.0, you would use milliseconds == 3000, etc.

Keep in mind that timers are not fired very precisely:

A timer is not a real-time mechanism; it fires only when one of the run loop modes to which the timer has been added is running and able to check if the timer’s firing time has passed.

You may find that when milliseconds==9000, more than 9 seconds has actually passed (but probably not much more). There are other tools available if more precise timing is required.

dreamlax