larick
larick

Reputation: 259

UIStepper value - garbage value returned after a number of iterations

I've solved the problem I was having as described in this post but want to understand the why of it (I spend a good amount of time figuring this out) as I've posed in the "Questions" below.

I had a problem with incrementing and decrementing the value returned when calling an IBAction method using UIStepper. When I ran and debugged the app I could step up and down and the log statements always reflected the intended stepper values but when I iteratively stepped up 0.1, 0.2 then 0.3 and then stepped down, when I got back to 0.0, when I performed the if test, the value for changeValue shown in the debugger was garbage and the test did not result in a true condition for == 0.0. Note that if I only stepped up to 0.2 then back down to 0.0, the if test for changeValue worked. It is only when I stepped up to 0.3 that I got the garbage value when I got back to 0.0.

Initially, to increment the stepper I set the stepValue property as:

viewStepper.stepvalue = 0.1

and the method returned the garbage value at 0.0 after stepping up to 0.3 and returning to 0.0.

When I changed the assignment to:

viewStepper.stepValue - 0.1f

problem solved - changeValue returns the intended 0.0 changeValue for my if test and the method works as intended regardless of the number of iterations.

Question: 1) I kind of get this but why if the stepValue is a double does the assignment value need to explicitly include the "f" and more curious to me 2) why did my test in the method work without the "f" when assigning the viewStepper.stepValue property when it did two step iterations, but returned garbage for changeValue when I did three iterations up and then returned back down to 0.0?

Here is the core of the method I was testing:

- (IBAction)doStepper:(UIStepper *)sender
{
   double changeValue = [sender value];
   NSLog(@"(double)change value %f", (double)changeValue);
   NSLog(@"sender value:%0.1f", [sender value]);

   if ((double)changeValue == 0.0) {
       if (!something) {
           // do stuff
       }
   // do stuff

   } else {
        // do stuff
   }
}

Upvotes: 0

Views: 602

Answers (1)

Joshua Honig
Joshua Honig

Reputation: 13215

Sounds like a classic case of floating-point rounding error. The general rule is don't compare floating point values for equality (==). In the second case you upped the precision of your number (to a double rather than the default single-precision float) so the integrity of your value lasted a few calculations longer. If you absolutely need to keep track of fine-grained exact decimal values, do one of the following:

  • Use the Decimal data type
  • Keep track of the underlying increment in an integer type but present it as a decimal. In your example, if your step is always 0.1 exactly, you could keep track of the number of steps as an integer but divide the number of steps by 10 to get the current useful value.

Upvotes: 2

Related Questions