我正在编写一种方法来计算一系列事件之间的平均时间间隔(特别是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的第一步,所以我希望答案不是太微不足道:))
答案 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;
}