使用"timeval_subtract“函数来查找两种结构时间类型之间的时间,有人能解释一下用于”通过更新y来执行后面减法的进位“和其他部分的目的和逐步数学吗?我理解这个函数的目的以及如何在一个程序中实现它,但我想了解它是如何在程序内部工作的,在任何地方都找不到任何解释,而且我似乎无法理解它。
int timeval_subtract (struct timeval *result, struct timeval *x,struct timeval *y)
{
/* Perform the carry for the later subtraction by updating y. */
if (x->tv_usec < y->tv_usec) {
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
y->tv_usec -= 1000000 * nsec;
y->tv_sec += nsec;
}
if (x->tv_usec - y->tv_usec > 1000000) {
int nsec = (y->tv_usec - x->tv_usec) / 1000000;
y->tv_usec += 1000000 * nsec;
y->tv_sec -= nsec;
}
/* Compute the time remaining to wait.
tv_usec is certainly positive. */
result->tv_sec = x->tv_sec - y->tv_sec;
result->tv_usec = x->tv_usec - y->tv_usec;
/* Return 1 if result is negative. */
return x->tv_sec < y->tv_sec;
}它是一个与GNU库相关的函数,用于确定经过的时间节点/运行-Time.html,因此我并不是在寻找改进,而是简单地解释为什么在其中进行除法、加减、减法和乘法。这些特定的算术操作实现了什么?/为什么它们被完成/没有完成?我已经完成了这一步,但仍然无法理解它。我会继续这样做,直到我这样做(甚至在有人向我解释之后),但我希望从已经理解它的人那里获得一些洞察力。这个平台是UNIX,这是我刚开始使用的,但我认为它不会改变函数内部正在进行的操作。与所使用的算法相比,它更多地是一个关于正在执行的算法的问题。
发布于 2022-07-27 17:26:16
下面是一个timeval_subtract():
回想一下,tv_usec是自tv_sec以来经过的微秒。
所以diff{-1,2000001} == diff{1,1}是真的,tv{0,-1} == tv{-1,999999}也是。
/* copied from
https://www.gnu.org/software/libc/manual/html_node/Calculating-Elapsed-Time.html
Changed input timevals to const, added // comments.
Changed condition of 2nd if.
*/
int
timeval_subtract (const struct timeval *x, const struct timeval *y, struct timeval *diff)
{
//subtraction found the difference, the minuend minus the subtrahend
timeval sh = *y; // mutable local copy of y, sh (the subtrahend)
/* Perform the carry for the later subtraction by updating sh. */
if (x->tv_usec < sh.tv_usec) {
// reduce sh.usecs so usec diff will be positive.
// carry or lend sh.usecs to sh.secs, in packages of 1e6 usecs (whole secs).
// as we are here, we know we must carry at least 1 sec (1 million usec)
int nsec = (sh.tv_usec - x->tv_usec) / 1000000 + 1;
sh.tv_usec -= 1000000 * nsec;
sh.tv_sec += nsec;
}
// if (x->tv_usec - sh.tv_usec > 1000000) { // could show tv{x,1000000}, not 'normal'
if (x->tv_usec - sh.tv_usec > 999999) { // normalize 0-999999
// normalize diff; increase sh.usecs so usec diff will be < 1000000.
// carry or lend whole sh.secs to sh.usecs
int nsec = (x->tv_usec - sh.tv_usec) / 1000000;
sh.tv_usec += 1000000 * nsec;
sh.tv_sec -= nsec;
}
// should now have the subtrahend sec/usec that will produce normalized difference
/* Compute the time remaining to wait.
tv_usec is certainly positive. */
diff->tv_sec = x->tv_sec - sh.tv_sec;
diff->tv_usec = x->tv_usec - sh.tv_usec;
/* Return 1 if diff is negative. */
return x->tv_sec < sh.tv_sec;
// timeval_subtract
}如果您需要同时支持32位和64位time_t类型,那么输出结果就会变得复杂,但是您可以使用如下所示调用timeval_subtract():
// replace MY_SPECIFIC_PREPROC_8B_DEF with your own
// preprocessor time_t distinguishing define
#if defined MY_SPECIFIC_PREPROC_8B_DEF
#define LSPEC "lld" // format specifier input length
char fmt[] = "% 020" LSPEC " % 011ld "; // long long tv_sec"
#define MAX_TIME_T 0x7fffffffffffffff
#define MIN_TIME_T 0x8000000000000000
#else
#define LSPEC "ld"
char fmt[] = "% 011" LSPEC " % 011ld "; // less chars for long tv_sec"
#define MAX_TIME_T 0x7fffffff
#define MIN_TIME_T 0x80000000
#endif
const time_t max_time_t = MAX_TIME_T;
const time_t min_time_t = MIN_TIME_T;
// Test overflow of both timeval members, sec & usec
struct timeval a = {min_time_t, 1}; // 1 usec > negative overflow
struct timeval b = {0, 0}; // our subtrahend, ++1 usec in loop
struct timeval c = {0, 0}; // holds result; difference in this case
strcat (fmt, "= a{%" LSPEC ",%ld} - b{%" LSPEC ",%ld}\n");
for (auto i=0; i<3; i++) {
timeval_subtract (&a,&b,&c);
Serial.printf(fmt,
c.tv_sec, c.tv_usec, a.tv_sec, a.tv_usec, b.tv_sec, b.tv_usec);
b.tv_usec += 1; // normal time flow
}
// Without an appropriate preprocessor define this may compile
for (auto i=0; i<3; i++) {
timeval_subtract (&a,&b,&c);
// explicit casts try to quiet compiler on other sized type_t systems
if (8 == sizeof(time_t)) {
Serial.printf("% 020lld % 011ld = a{%lld,%ld} - b{%lld,%ld}\n",
(long long)c.tv_sec, c.tv_usec,
(long long)a.tv_sec, a.tv_usec,
(long long)b.tv_sec, b.tv_usec);
}
else if (4 == sizeof(time_t)) {
Serial.printf("% 011ld % 011ld = a{%ld,%ld} - b{%ld,%ld}\n",
(long)c.tv_sec, c.tv_usec,
(long)a.tv_sec, a.tv_usec,
(long)b.tv_sec, b.tv_usec);
}
b.tv_usec += 1; // normal time flow
}https://stackoverflow.com/questions/15846762
复制相似问题