我创建了一个脚本来收集秒和microsec的时间戳。然后我试图计算这些值的差异。只要整数是正数,结果就像预期的那样。
作为下一步,我将整数转换为字符串,并将它们连接在一起。用户可以更容易地阅读人类可读的格式。
当整数为负时,会出现问题。首先,当我将负int转换为字符串时,我无法弄清楚如何打印负号。 (例如3sec。-3microsec)
其次,如果两个整数都是负数并且我有两个负号,那么它可能会变得更糟。 (例如-3sec。-3microsec)
所以我的问题是,因为我试图减去两个整数,实际上是浮点数是否有任何其他替代方法,我可以将它们连接成浮点数然后应用减法? (例如int 3sec int 3microsec concatenation to float 3.3sec)
我是C语言的初学者所以我不确定这是否可能,这就是我在所有这个过程中完成的原因(将int转换为字符串然后连接)。
可执行代码示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <sys/timeb.h>
#include <inttypes.h>
#include <assert.h>
#define TIME_CHAR 22
#define PROCESS_CHARACTERS 32
typedef struct rec {
char time_1[TIME_CHAR];
char time_2[TIME_CHAR];
char time_3[TIME_CHAR];
char process[PROCESS_CHARACTERS];
}RECORD;
char *u2s(long unsigned int number) {
RECORD *ptr_record = malloc (sizeof(RECORD));
if (ptr_record == NULL) {
printf("Out of memory!\nExit!\n");
exit(0);
}
const int n = snprintf(NULL, 0, "%lu", number);
assert(n > 0);
char buf[n+1];
snprintf(buf, n+1, "%lu", number);
assert(buf[n] == '\0');
memcpy(ptr_record->process, buf , sizeof buf);
return ptr_record->process;
}
uint32_t ClockGetTime() {
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
return (int32_t)ts.tv_sec * 1000000LL + (int32_t)ts.tv_nsec / 1000LL;
}
void cleanup(RECORD** ptr_record) {
free(*ptr_record);
*ptr_record = NULL;
}
int main(int argc, char *argv[]) {
char *dot = ".";
RECORD *ptr_record;
ptr_record = malloc (sizeof(RECORD));
if (ptr_record == NULL) {
printf("Out of memory!\nExit!\n");
exit(0);
}
/* Originate Time Stamps for time_1 */
time_t time_1_sec = time(NULL);
uint32_t client_1_sec = time_1_sec;
uint32_t client_1_microsec = ClockGetTime();
char *client_1_sec_string = u2s(client_1_sec);
char *client_1_microsec_string = u2s(client_1_microsec);
memset( ptr_record->time_1 , '\0' , sizeof ptr_record->time_1 );
strncat( ptr_record->time_1 , client_1_sec_string , strlen(client_1_sec_string) );
strncat( ptr_record->time_1 , dot , strlen(dot) );
strncat( ptr_record->time_1 , client_1_microsec_string , strlen(client_1_microsec_string) );
/* Originate Time Stamps for time_2 */
time_t time_2_sec = time(NULL);
uint32_t client_2_sec = time_2_sec;
uint32_t client_2_microsec = ClockGetTime();
char *client_2_sec_string = u2s(client_2_sec);
char *client_2_microsec_string = u2s(client_2_microsec);
memset( ptr_record->time_2 , '\0' , sizeof ptr_record->time_2 );
strncat( ptr_record->time_2 , client_2_sec_string , strlen(client_2_sec_string) );
strncat( ptr_record->time_2 , dot , strlen(dot) );
strncat( ptr_record->time_2 , client_2_microsec_string , strlen(client_2_microsec_string) );
printf("This is buffer time_2: %s\n",ptr_record->time_2);
int32_t d_positive_sec = client_2_sec - client_1_sec;
int32_t d_positive_microsec = client_2_microsec - client_1_microsec;
printf("This is the positive difference in sec: %"PRId32"\n",d_positive_sec);
printf("This is the positive difference in microsec: %"PRId32"\n",d_possitive_microsec);
int32_t d_negative_sec = client_1_sec - client_2_sec;
int32_t d_negative_microsec = client_1_microsec - client_2_microsec;
printf("This is the negative difference in sec: %"PRId32"\n",d_negative_sec);
printf("This is the negative difference in microsec: %"PRId32"\n",d_negative_microsec);
char *n_sec_string = u2s(d_negative_sec);
char *n_microsec_string = u2s(d_negative_microsec);
memset( ptr_record->time_3 , '\0' , sizeof ptr_record->time_3 );
strncat( ptr_record->time_3 , n_sec_string , strlen(n_sec_string) );
strncat( ptr_record->time_3 , dot , strlen(dot) );
strncat( ptr_record->time_3 , n_microsec_string , strlen(n_microsec_string) );
printf("This is negative concatenated %s\n",ptr_record->time_3);
cleanup(&ptr_record);
return 0;
} /* End of main(){} */
输出样本:
This is the positive difference in sec: 0
This is the positive difference in microsec: 37
This is the negative difference in sec: 0
This is the negative difference in microsec: -37
This is negative concatenated 0.18446744073709551579
很容易判断,在连接后我们应该看到(0.-37),最好的结果是(-0.37)。
答案 0 :(得分:0)
You can/should read all about printf format conversions at:
<http://en.wikipedia.org/wiki/Printf_format_string#Format_placeholders>
which states:
the full syntax of a conversion parameter is:
**%[parameter][flags][width][.precision][length]type**
where [parameter] is a posix extension ... (see linked page for details)
标志可以是零或更多(以任何顺序):
Character Description
**+ always denote the sign '+' or '-' of a number (the default is to omit the sign for positive numbers). Only applicable to numeric types.**
space prefixes non-negative signed numbers with a space
- left-align the output of this placeholder (the default is to right-align the output).
# Alternate form. For 'g' and 'G', trailing zeros are not removed. For 'f', 'F', 'e', 'E', 'g', 'G', the output always contains a decimal point. For 'o', 'x', and 'X', a 0, 0x, and 0X, respectively, is prepended to non-zero numbers.
0 use 0 instead of spaces to pad a field when the width option is specified. For example, printf("%2d", 3) results in " 3", while printf("%02d", 3) results in "03".
Width指定要输出的最小字符数,通常用于填充表格化输出中的固定宽度字段,否则字段会更小,尽管它不会导致超大字段的截断。宽度值中的前导零被解释为上面提到的零填充标记,并且负值被视为与左对齐相关的正值&#34; - &#34;国旗也在上面提到。
Precision通常指定输出的最大限制,具体取决于特定的格式类型。对于浮点数字类型,它指定输出应舍入的小数点右侧的位数。对于字符串类型,它限制了应输出的字符数,之后字符串将被截断。
长度可以省略,也可以是以下任何一种:
Character Description
hh For integer types, causes printf to expect an int-sized integer argument which was promoted from a char.
h For integer types, causes printf to expect an int-sized integer argument which was promoted from a short.
l For integer types, causes printf to expect a long-sized integer argument.
For floating point types, causes printf to expect a double argument.
ll For integer types, causes printf to expect a long long-sized integer argument.
L For floating point types, causes printf to expect a long double argument.
z For integer types, causes printf to expect a size_t-sized integer argument.
j For integer types, causes printf to expect a intmax_t-sized integer argument.
so just include the '+' flag in the format conversion parameter and
if the value is negative, then a '-' will be printed in the output
t For integer types, causes printf to expect a ptrdiff_t-sized integer argument.
答案 1 :(得分:0)
second
和microsecond
,但是在2个调用和秒数之间经过的时间可能会增加。相反,请重新编写ClockGetTime()
以同时获取sec
和microsec
。
// time_t time_1_sec = time(NULL);
// uint32_t client_1_sec = time_1_sec;
// uint32_t client_1_microsec = ClockGetTime();
正如@alk所建议的那样,隐藏到一个共同的比例,然后减去
// int32_t d_positive_sec = client_2_sec - client_1_sec;
// int32_t d_positive_microsec = client_2_microsec - client_1_microsec;
// printf("This is the positive difference in sec: %"PRId32"\n",d_positive_sec);
// printf("This is the positive difference in microsec: %"PRId32"\n",
// d_possitive_microsec);
int64_t t1 = client_1_sec;
t1 = t1*1000000 /* microseconds per second */ + client_1_microsec;
int64_t t2 = client_2_sec;
t2 = t2*1000000 + client_2_microsec;
int64_t diff = t2 - t1;
int64_t diff_sec = diff/1000000;
int32_t diff_usec = diff%1000000;
if (diff_usec < 0) diff_usec = -diff_usec;
printf("Difference: %" PRId64 ".%06" PRId32 " sec\n", diff_sec, diff_usec);
转换为float
通常无法提供足够的精确度。转换为double
通常对于32位int
和~20位usec来说足够精确。这是另一种方法。
double t1 = client_1_sec;
t1 = t1*1000000 /* microseconds per second */ + client_1_microsec;
double t2 = client_2_sec;
t2 = t2*1000000 + client_2_microsec;
double diff = t2 - t1;
printf("Difference: %0.6f sec\n", diff);
总的来说,建议改为使用int64_t
来存储clock_gettime()
的秒和纳秒,并在差值计算中使用它。
int64_t ClockGetTime(void) {
struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts)) Handle_Error();
return ts.tv_sec * ((int64_t)1000000000) + ts.tv_nsec;
}
次要说明
u2s
在构造数字的字符串表示时经过大量工作,小心不要溢出buf
。然而,如果没有检查memcpy(ptr_record->process, buf , sizeof buf)
,我很高兴sizeof buf <= sizeof ptr_record->process
。