在NSMutableArray中存储浮动会产生意外结果

时间:2010-11-17 21:30:22

标签: objective-c cocoa ios4

我正在编写一种方法来计算一系列事件之间的平均时间间隔(特别是iPhone中的按钮点击)。由于我想要平均的时间间隔的数量可能会在程序的生命周期中发生变化,因此我将时间读数存储在tapTimes类型NSMutableArray的对象中,因此我不必担心管理数组大小。

当我将时间读数存储为双精度数时,一切正常(为简单起见,在下面的示例中,我只对一个时间间隔感兴趣):

CFAbsoluteTime time = CFAbsoluteTimeGetCurrent();
[tapTimes addObject:[NSNumber numberWithDouble:(double)time]];
[tapTimes removeObjectAtIndex:0];
double deltaT = [[tapTimes objectAtIndex:1] doubleValue] - [[tapTimes objectAtIndex:0] doubleValue];

其中,对于每秒左右的敲击,给出(第一个值是第一次读取,因为数组是用零初始化的):

deltaT 311721948.947153
deltaT 1.023200
deltaT 1.080004
deltaT 1.055961
deltaT 1.087942
deltaT 1.080074

但是,如果我存储花车:

CFAbsoluteTime time = CFAbsoluteTimeGetCurrent();
[tapTimes addObject:[NSNumber numberWithFloat:(float)time]];
[tapTimes removeObjectAtIndex:0];
float deltaT = [[tapTimes objectAtIndex:1] floatValue] - [[tapTimes objectAtIndex:0] floatValue];

然后我得到deltaT的意外结果:

deltaT 311721760.000000
deltaT 0.000000
deltaT 0.000000
deltaT 0.000000
deltaT 0.000000
deltaT 32.000000
deltaT 0.000000
deltaT 0.000000
deltaT 0.000000

知道出了什么问题吗? (我正在做Objective-c / cocoa的第一步,所以我希望答案不是太微不足道:))

1 个答案:

答案 0 :(得分:3)

问题是float不够精确,不能在一秒钟后从时间戳中告诉一个时间戳。坚持double;有CFAbsoluteTime使用该类型的原因。

以下是64位10.6.4下的问题演示:

val: 311721760.000000 - val2: 311721761.000000 - (val2 - val): 1.000000
v: 311721760.000000 - v2: 311721760.000000 - (v2 - v): 0.000000

第一行使用了double个值;通过将val2添加到1生成了val。第二行使用float值。源代码如下:

//clang so_float.m -o so_float
#import <stdio.h>

int
main(void) {
  double val = 311721760.000000;
  double val2 = val + 1.0;
  fprintf(stderr, "val: %f - val2: %f - (val2 - val): %f\n", val, val2, val2 - val);
  float v = val;
  float v2 = val + 1.0;
  fprintf(stderr, "v: %f - v2: %f - (v2 - v): %f\n", v, v2, v2 - v);
  return 0;
}