C中long的减法会失去精度吗?

Subtraction of long in C loses precision?

我相信答案很简单,但我不太明白。我正在尝试使用此代码计算两个 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.,这似乎表明我丢失了纳秒的最后三位数字(因为它们不应该总是零)。有人可以指出是什么原因造成的吗?

Elapsed time: 0.300876000 seconds. which seems to indicate that I'm losing the last three digits of the nanoseconds (since those shouldn't always be zero). Can someone point out what's causing that?

代码的时钟报告精度为 1000 ns。

and/or

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 时 "borrow" 数学不正确。

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 之前,那么可能需要其他代码来保持 diff 的 2 个成员具有相同的符号。