Вычитание long в C теряет точность?

Я уверен, что ответ прост, но я не совсем понимаю. Я пытаюсь вычислить дельту между двумя struct timespec используя этот код:

struct timespec start, finish, diff;
int ndiff;

/* Structs are filled somewhere else */

diff.tv_sec = finish.tv_sec - start.tv_sec;
ndiff = finish.tv_nsec - start.tv_nsec;
if (ndiff < 0) {
    diff.tv_sec--;
    ndiff = 1L - ndiff;
}
diff.tv_nsec = ndiff;

printf("Elapsed time: %ld.%ld seconds.\n", diff.tv_sec, diff.tv_nsec);

Однако на выходе всегда что-то вроде Elapsed time: 0.300876000 seconds. который, кажется, указывает на то, что я теряю последние три цифры наносекунд (поскольку они не всегда должны быть равны нулю). Кто-то может указать, что это вызывает?

1 ответ

Решение

Истекшее время: 0,300876000 секунд. который, кажется, указывает на то, что я теряю последние три цифры наносекунд (поскольку они не всегда должны быть равны нулю). Кто-то может указать, что это вызывает?

Точность кода часов равна 1000 нс. @ Джон Боллинджер @rici

и / или

diff.tv_sec не обязательно long, Используйте соответствующий спецификатор.

// printf("Elapsed time: %ld.%ld seconds.\n", diff.tv_sec, diff.tv_nsec);
// Also insure fraction is printed with 9 digits
printf("Elapsed time: %lld.%09ld seconds.\n", (long long) diff.tv_sec, diff.tv_nsec);

Кроме того, неверная математика "позаимствовать" при обновлении ndiff,

ndiff = finish.tv_nsec - start.tv_nsec;
if (ndiff < 0) {
  diff.tv_sec--;
  // ndiff = 1L - ndiff;
  ndiff += 1000000000;
}

Еще лучше бросьте int diff переменная.

diff.tv_sec = finish.tv_sec - start.tv_sec;
diff.tv_nsec = finish.tv_nsec - start.tv_nsec;
if (diff.tv_nsec < 0) {
    diff.tv_sec--;
    diff.tv_nsec += 1000000000;
}

Должен finish происходят раньше startтогда может потребоваться другой код, чтобы сохранить 2 члена diff с таким же знаком.

Другие вопросы по тегам