Objective C中的浮点值除法错误

Posted

技术标签:

【中文标题】Objective C中的浮点值除法错误【英文标题】:Float values dividing error in Objective C 【发布时间】:2012-03-01 09:11:06 【问题描述】:

当我运行这段代码时:

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;

显示以下输出:

 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

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

在哪里,您可以看到,在输出的最后一个块中,(int)(f / tickIncrement) : 1 必须返回 2,而是返回 1。

为什么会这样?

【问题讨论】:

【参考方案1】:

您很可能会遇到浮点表示问题。 尝试使用双精度,但要知道它不会解决根本问题,您看到的 2.0 实际上是 1.99999 ...,它只是被格式化为显示 2.0

阅读“What Every Computer Scientist Should Know About Floating-Point Arithmetic”

同时,尝试简单地使用:

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

【讨论】:

以上是关于Objective C中的浮点值除法错误的主要内容,如果未能解决你的问题,请参考以下文章

Java中浮点除法中的严重数字损坏? [复制]

Objective-C - 对 nan 进行浮点检查

Objective C - 通过选择器传递浮点数

带有浮点数据的 C 数组在 Objective C 类中崩溃 (EXC_BAD_ACCESS)

数学库中的除法函数如何处理除法运算符无法做到的精度误差?

接近零的浮点值会导致被零除的错误吗?