Saru
Saru

Reputation: 861

Float values dividing error in Objective C

When I run this block of code :

float angle = startAngle;
int i = 0;

for (float f = self.minNumber; f <= self.maxNumber; f += minorTickIncrement) {
    points[i++] = CGPointMake(centerX + cos(angle) * (radius - tickInset), centerY + sin(angle) * (radius - tickInset));

    CGFloat myTickLength;

    NSLog(@"f : %f",f);
    NSLog(@"tickIncrement : %f",tickIncrement);
    NSLog(@"f / tickIncrement : %f",f / tickIncrement);
    NSLog(@"(int)(f / tickIncrement) : %d",(int)(f / tickIncrement));
    NSLog(@"(f / tickIncrement - (int)(f / tickIncrement)) : %f",(f / tickIncrement - (int)(f / tickIncrement)));
    NSLog(@"fabs((f / tickIncrement - (int)(f / tickIncrement))) : %f",fabs((f / tickIncrement - (int)(f / tickIncrement))));

    float checkValue = (f / tickIncrement - (int)(f / tickIncrement));

    if (fabs(checkValue) < 0.05) { // if is major tick
        myTickLength = self.tickLength;
        NSString *string = [[NSString alloc] initWithFormat:@"%0.1f", f];
        float textWidth = textHeight * [string length] / 2;
        CGContextShowTextAtPoint(ctx, centerX + cos(angle) * (radius - textInset) - textWidth / 2.0, centerY + sin(angle) * (radius - textInset) + textHeight / 4.0, [string UTF8String], [string length]);
        [string release];

    } else {
        myTickLength = self.minorTickLength;
    }

    points[i++] = CGPointMake(centerX + cos(angle) * (radius - myTickLength - tickInset), centerY + sin(angle) * (radius - myTickLength - tickInset));

    angle += minorTickAngleIncrement;
}

The following output is been displayed :

 f : 0.100000
 tickIncrement : 0.100000
 f / tickIncrement : 1.000000
 (int)(f / tickIncrement) : 1
 (f / tickIncrement - (int)(f / tickIncrement)) : 0.000000
  fabs((f / tickIncrement - (int)(f / tickIncrement))) : 0.000000

  f : 0.120000
 tickIncrement : 0.100000
 f / tickIncrement : 1.200000
 (int)(f / tickIncrement) : 1
 (f / tickIncrement - (int)(f / tickIncrement)) : 0.200000
 fabs((f / tickIncrement - (int)(f / tickIncrement))) : 0.200000

 f : 0.140000
 tickIncrement : 0.100000
 f / tickIncrement : 1.400000
 (int)(f / tickIncrement) : 1
 (f / tickIncrement - (int)(f / tickIncrement)) : 0.400000
 fabs((f / tickIncrement - (int)(f / tickIncrement))) : 0.400000

 f : 0.160000
 tickIncrement : 0.100000
 f / tickIncrement : 1.600000
 (int)(f / tickIncrement) : 1
 (f / tickIncrement - (int)(f / tickIncrement)) : 0.600000
 fabs((f / tickIncrement - (int)(f / tickIncrement))) : 0.600000

 f : 0.180000
 tickIncrement : 0.100000
 f / tickIncrement : 1.800000
 (int)(f / tickIncrement) : 1
 (f / tickIncrement - (int)(f / tickIncrement)) : 0.800000
 fabs((f / tickIncrement - (int)(f / tickIncrement))) : 0.800000

 f : 0.200000
 tickIncrement : 0.100000
 f / tickIncrement : 2.000000
 **(int)(f / tickIncrement) : 1**
 (f / tickIncrement - (int)(f / tickIncrement)) : 1.000000
 fabs((f / tickIncrement - (int)(f / tickIncrement))) : 1.000000

...................

Where, you can see that in the last block of output (int)(f / tickIncrement) : 1 must return 2, but instead it returns 1.

Why does this happen?

Upvotes: 0

Views: 181

Answers (1)

Prashant Kumar
Prashant Kumar

Reputation: 22669

Most likely, you're running into floating point representation problems.
Try using a double, but know that it isn't going to solve the underlying problem, that the 2.0 you see is actually 1.99999 ... that is simply getting formatted to show 2.0

Read "What Every Computer Scientist Should Know About Floating-Point Arithmetic"

In the meantime, try simply using:

(int)(f / tickIncrement + tickIncrement / 5.0)

Upvotes: 5

Related Questions