Хранение чисел в NSMutableArray дает неожиданные результаты - PullRequest
0 голосов
/ 18 ноября 2010

Я пишу метод, который вычисляет средний интервал времени между сериями событий (в частности, нажатие кнопок в 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 Ответ

3 голосов
/ 18 ноября 2010

Проблема в том, что 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...