我想从double初始化timespec结构。如何实现小数部分到纳秒的精确转换?
double x = 10.1;
struct timespec tp;
tp.tv_sec = (long) x;
tp.tv_nsec = (x - tp.tv_sec) * 1000000000L;
printf("%ld %ld\n", tp.tv_sec, tp.tv_nsec);
// 10 99999999 <- actual (BAD)
// 10 100000000 <- expected
这似乎是一个经典的浮点挑战。用于提取积分和分数的确切方法无关紧要(ex modf)。
我目前的解决方法是将double转换为四舍五入到所需精度的字符串并提取这两个部分。
static const int CLOCK_PRECISION = 1;
char nanos[] = "000000000";
char str[25]; // arbitrary size suits my needs
/** Converted string length (excluding '\0'). */
int len = snprintf(str, sizeof(str), "%.*f", CLOCK_PRECISION, b);
/** Position of first decimal digit in the string. */
char *decOfs = strchr(str, '.') + 1;
/** Number of decimal digits. */
size_t decLen = len - (decOfs - str);
memcpy(nanos, decOfs, decLen);
a->tv_sec = atol(str);
a->tv_nsec = atol(nanos);
我甚至考虑了一种直接从字符串(例如:“10.1”)初始化的变通方法。这是可行的,因为我的初始化值不随时间而改变。
解决我最初的问题? 有没有更好的想法来初始化timespec?
我想要一个可扩展的解决方案。我不想从十分之一秒或百分之一秒开始。
答案 0 :(得分:3)
只需将其添加到顶部附近:
x += 0.5e-9.
这将增加一半&#34; epsilon&#34; (最小值变化)对于timespec的最大精度,有效地&#34;舍入&#34;输入。请注意,如果x的值超过15个十进制数字的精度,它将永远不会准确,因为所有双倍给你。但是如果你&#34;围绕&#34;那么10.1应该可以正常工作。如上所述。