2010-11-17 82 views
0

我正在寫一種方法來計算一系列事件(特別是iPhone中的按鈕敲擊)之間的平均時間間隔。由於在程序生命週期中,我想要平均的時間間隔數可能會發生變化,因此我將時間讀數存儲在類型爲NSMutableArray的對象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的第一步,所以我希望答案不是太簡單:))

回答

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; 
} 
+0

只是檢查我得到它正確::如果我使用(IEEE 754)單精度浮點數來表示我的**時間**讀數,我有23位分辨率的小數部分尾數。因爲2^-23是約。 1e-7,我穿過'1秒'的分辨率極限,指數約爲1。 24,因爲2^24〜1.6e7,大約是。在格林威治標準時間2001年1月1日00:00:00的參考日期之後的6個月(翻譯秒到月)。所以,我在最後一次使用1秒分辨率的浮動機會後約9年:) – 2010-11-18 09:31:29

相關問題