哪种格式字符串与printf()一起使用的时间为789:01.234

CoS*_*oCo 1 c formatting time printf

我想从一个双精度点打印一个以分钟和秒为单位的时间,包括它们的小数部分(最多6位),而不用零结尾。

由于格式的本质,应该有可能在单个printf()语句中将解决方案嵌套在其他参数中!

我要打印的时间变量是秒单位的两倍,并且不超过几十小时的范围。

    double time1 = 123.456789; //   2:03.456789 some text
    double time2 = 12345.6;    // 205:45.6 some text
    printf("format: %-16s time1: %.6g some text\n", "%.6g", time1);
    printf("format: %-16s time2: %.6g some text\n", "%.6g", time2);
    printf("format: %-16s time1: %3d:%09.6f some text\n", "%3d:%09.6f", (int)time1 / 60, fmod(time1, 60));
    printf("format: %-16s time2: %3d:%09.6f some text\n", "%3d:%09.6f", (int)time2 / 60, fmod(time2, 60));
    printf("format: %-16s time1: %3d:%09.6g some text\n", "%3d:%09.6g", (int)time1 / 60, fmod(time1, 60));
    printf("format: %-16s time2: %3d:%09.6g some text\n", "%3d:%09.6g", (int)time2 / 60, fmod(time2, 60));
    printf("format: %-16s time1: %3d:%0.6g some text\n", "%3d:%0.6g", (int)time1 / 60, fmod(time1, 60));
    printf("format: %-16s time2: %3d:%0.6g some text\n", "%3d:%0.6g", (int)time2 / 60, fmod(time2, 60));
    printf("format: %-16s time1: %3d:%02d%.6f some text\n", "%3d:%02d%.6f", (int)time1 / 60, (int)time1 % 60, fmod(time1, 1));
    printf("format: %-16s time2: %3d:%02d%.6f some text\n", "%3d:%02d%.6f", (int)time2 / 60, (int)time2 % 60, fmod(time2, 1));
    printf("format: %-16s time1: %3d:%02d%.6g some text\n", "%3d:%02d%.6g", (int)time1 / 60, (int)time1 % 60, fmod(time1, 1));
    printf("format: %-16s time2: %3d:%02d%.6g some text\n", "%3d:%02d%.6g", (int)time2 / 60, (int)time2 % 60, fmod(time2, 1));
    printf("format: %-16s time1: %3d:%02d%0.6g some text\n", "%3d:%02d%0.6g", (int)time1 / 60, (int)time1 % 60, fmod(time1, 1));
    printf("format: %-16s time2: %3d:%02d%0.6g some text\n", "%3d:%02d%0.6g", (int)time2 / 60, (int)time2 % 60, fmod(time2, 1));
Run Code Online (Sandbox Code Playgroud)

预期:

time1:   2:03.456789 some text
time2: 205:45.6 some text
Run Code Online (Sandbox Code Playgroud)

结果:

format: %.6g             time1: 123.457 some text
format: %.6g             time2: 12345.6 some text
format: %3d:%09.6f       time1:   2:03.456789 some text   <- OK
format: %3d:%09.6f       time2: 205:45.600000 some text   <- trailing zeros
format: %3d:%09.6g       time1:   2:003.45679 some text   <- 3 digits for minutes, missing 8
format: %3d:%09.6g       time2: 205:0000045.6 some text   <- 7 digits for minutes
format: %3d:%0.6g        time1:   2:3.45679 some text     <- 1 digit for minutes, missing 8
format: %3d:%0.6g        time2: 205:45.6 some text        <- OK
format: %3d:%02d%.6f     time1:   2:030.456789 some text  <- leading 0
format: %3d:%02d%.6f     time2: 205:450.600000 some text  <- leading 0, trailing zeros
format: %3d:%02d%.6g     time1:   2:030.456789 some text  <- leading 0
format: %3d:%02d%.6g     time2: 205:450.6 some text       <- leading 0
format: %3d:%02d%0.6g    time1:   2:030.456789 some text  <- leading 0
format: %3d:%02d%0.6g    time2: 205:450.6 some text       <- leading 0
Run Code Online (Sandbox Code Playgroud)

另一种格式会很好:

time2: 3:25:45.6 some text
Run Code Online (Sandbox Code Playgroud)

chq*_*lie 5

对于正的时间值,请尝试以下格式:

printf("%d:%d%g\n",
       (int)time / 60,              // number of minutes
       (int)time % 60 / 10,         // number of tens of seconds
       time - (int)time / 10 * 10); // number of seconds units and fraction thereof
Run Code Online (Sandbox Code Playgroud)

但是请注意,如果分数值大于或等于该值将不起作用,0.9999995因为最后一项将舍入到下一个整数。

将时间转换为整数微秒并以这种方式打印会更安全:

int us = (int)(time * 1000000 + 0.5);
printf("%d:%02d.%06d\n", us / 60000000, us / 1000000 % 60, us % 1000000);
Run Code Online (Sandbox Code Playgroud)

用这种方法去掉尾随的零点会更加乏味,恐怕使用函数会更好。正确处理无限值和nan等极端情况并保持正确的舍入是很难的。

这是一个测试程序的示例:

#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// print a time in minutes and seconds with up to <places> decimal places and correct rounding
char *format_time(char *dest, size_t size, double time, int places) {
    char buf[400];
    int len = snprintf(buf, sizeof buf, "%.*f", places, time);
    int sign = (*buf == '-');
    char *p = strchr(buf, '.');
    if (p != NULL) {
        *p = '\0';
        double rounded_time = atof(buf + sign);
        double seconds = fmod(rounded_time, 60);
        double minutes = (rounded_time - seconds) / 60;
        *p = '.';
        len -= (p - buf);
        while (p[len - 1] == '0')
            len--;
        if (len == 1)
            len--;
        snprintf(dest, size, "%.*s%.0f:%02.0f%.*s",
                 sign, buf, minutes, seconds, len, p);
    } else {
        snprintf(dest, size, "%s", buf);
    }
    return dest;
}

#ifndef DBL_MAX
#define DBL_MAX  1.7976931348623157e+308
#endif

int main() {
    double a[] = {
        0, 1, 59, 60, 61,
        121.1, 121.11, 121.111, 121.1111, 121.11111, 121.111111,
        4321.0, 12345.6, 123.456789,
        129.9999994, 129.9999995,
        599.9999994, 599.9999995, 599.99999951, 599.9999999,
        23.9999999999, 59.9999994, 59.9999996,
        999.0000005, 1000.0000005, 999.9999999,
        1e6, 1e10, 1e12, 1e15, 1e18, 1e20, 1e25, 1e30,
        INT_MAX * 60.0, INT_MAX * 60.0 + 1234,
        (double)ULLONG_MAX * 64.0, DBL_MAX, 1.0 / 0.0, (double)NAN,
    };

    for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); i++) {
        char buf[400];
        printf("%32.16g --> %s\n", a[i], format_time(buf, sizeof buf, a[i], 6));
        printf("%32.16g --> %s\n", -a[i], format_time(buf, sizeof buf, -a[i], 6));
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

                               0-> 0:00
                              -0-> -0:00
                               1-> 0:01
                              -1-> -0:01
                              59-> 0:59
                             -59-> -0:59
                              60-> 1:00
                             -60-> -1:00
                              61-> 1:01
                             -61-> -1:01
                           121.1-> 2:01.1
                          -121.1-> -2:01.1
                          121.11-> 2:01.11
                         -121.11-> -2:01.11
                         121.111-> 2:01.111
                        -121.111-> -2:01.111
                        121.1111-> 2:01.1111
                       -121.1111-> -2:01.1111
                       121.11111-> 2:01.11111
                      -121.11111-> -2:01.11111
                      121.111111-> 2:01.111111
                     -121.111111-> -2:01.111111
                            4321-> 72:01
                           -4321-> -72:01
                         12345.6-> 205:45.6
                        -12345.6-> -205:45.6
                      123.456789-> 2:03.456789
                     -123.456789-> -2:03.456789
                     129.9999994-> 2:09.999999
                    -129.9999994-> -2:09.999999
                     129.9999995-> 2:10
                    -129.9999995-> -2:10
                     599.9999994-> 9:59.999999
                    -599.9999994-> -9:59.999999
               599.9999994999999-> 9:59.999999
              -599.9999994999999-> -9:59.999999
                    599.99999951-> 10:00
                   -599.99999951-> -10:00
                     599.9999999-> 10:00
                    -599.9999999-> -10:00
                   23.9999999999-> 0:24
                  -23.9999999999-> -0:24
                      59.9999994-> 0:59.999999
                     -59.9999994-> -0:59.999999
                      59.9999996-> 1:00
                     -59.9999996-> -1:00
               999.0000005000001-> 16:39.000001
              -999.0000005000001-> -16:39.000001
                    1000.0000005-> 16:40.000001
                   -1000.0000005-> -16:40.000001
                     999.9999999-> 16:40
                    -999.9999999-> -16:40
                         1000000-> 16666:40
                        -1000000-> -16666:40
                     10000000000-> 166666666:40
                    -10000000000-> -166666666:40
                   1000000000000-> 16666666666:40
                  -1000000000000-> -16666666666:40
                1000000000000000-> 16666666666666:40
               -1000000000000000-> -16666666666666:40
                           1e + 18-> 16666666666666666:40
                          -1e + 18-> -16666666666666666:40
                           1e + 20-> 1666666666666666752:40
                          -1e + 20-> -1666666666666666752:40
                           1e + 25-> 166666666666666697424896:04
                          -1e + 25-> -166666666666666697424896:04
                           1e + 30-> 16666666666666666704873979904:16
                          -1e + 30-> -16666666666666666704873979904:16
                    128849018820-> 2147483647:00
                   -128849018820-> -2147483647:00
                    128849020054-> 2147483667:34
                   -128849020054-> -2147483667:34
           1.180591620717411e + 21-> 19676527011956854784:04
          -1.180591620717411e + 21-> -19676527011956854784:04
          1.797693134862316e + 308-> 2996155224770526471302168869341711813188863443303040828151933426890179148788615168103226874770040896498710950234612783266345520226229959458788419419124700807563385759480436831271585473539816641201208858853854529842024245866346857407520574852654654654752654654654654760752752654654654-230-8257608251
         -1.797693134862316e + 308-> -29961552247705264713021688693417118131888634433030408281519334268901791487886151681032268747700700964964109502346127832663455202262299594587884194197007005633857594804368312760854735398166412012088488524438545298420245258684256784275245080654654654654654752654654654654654654842842842654842654654654752842842654654654692842654690692654692094654654692094654685692654692654692654692654692654692654692654692654692654654654692654654654692685692654654654692654692654692654654654692654692654692654692654692654654690842654690692685692685692
                             inf-> inf
                            -inf-> -inf
                             楠->楠
                             楠->楠

  • @chux:是的,您是对的,我很懒。答案已更新。其余的极端情况包括非限定时间和巨大的时间跨度。 (2认同)