如果是整数,则使用sprintf格式化浮点数,不带小数位

时间:2013-01-24 10:53:05

标签: c floating-point printf

最初我使用带有浮点数的sprintf总是带有2位小数,使用以下代码:

static void MyFunc(char* buffer, const float percentage)
{
    sprintf(buffer, "%.2f", percentage);
}

传递的百分比值之一是0x419FFFFF 20(调试器视图),这打印到缓冲区20.00。

我希望在不是整数时显示2位小数,例如

94.74 displayed as 94.74
94.7  displayed as 94.70
0     displayed as 0
5     displayed as 5
100   displayed as 100

我目前正在使用以下代码:

static void MyFunc(char* buffer, const float percentage)
{
    int fractional_part = ((percentage - (int)percentage) * 100);
    if (0 == fractional_part)
    {
        sprintf(buffer, "%d", (int)percentage);
    }
    else
    {
        sprintf(buffer, "%.2f", percentage);
    }
}

现在如果传递了0x419FFFFF 20(调试器视图),则小数部分计算为99.我假设则fractional_part的总和最终为(19.99 - 19)* 100 = 99.为什么第一个示例不打印19.99进入缓冲区?

我的问题的正确解决方案是什么?

2 个答案:

答案 0 :(得分:3)

你的是近似问题。

假设百分比是19.999。然后fractional_part将为99,并且将调用浮点分支。

但是打印带有两位小数的19.999会将其四舍五入为20.00,而 就是打印出来的。

您总是可以使用浮点分支,以获得一致的结果,然后截断为'。'如果它出现'.00'。否则,您冒着考试的风险,并且printf的内部成员会在某个时间发生争执。

#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
        float percentage = 19.999;
        char buffer[50];

        for (percentage = 19.990; percentage < 20.001; percentage += 0.001)
        {
                sprintf(buffer, "%.2f", percentage);
                char *p = strstr(buffer, ".00");
                if (p) *p = 0x0;
                printf("%.3f rendered as %.2f and becomes %s\n", percentage, percentage, buffer);
        }
        return 0;
}

19.990 rendered as 19.99 and becomes 19.99
19.991 rendered as 19.99 and becomes 19.99
19.992 rendered as 19.99 and becomes 19.99
19.993 rendered as 19.99 and becomes 19.99
19.994 rendered as 19.99 and becomes 19.99
19.995 rendered as 19.99 and becomes 19.99
19.996 rendered as 20.00 and becomes 20
19.997 rendered as 20.00 and becomes 20
19.998 rendered as 20.00 and becomes 20
19.999 rendered as 20.00 and becomes 20
20.000 rendered as 20.00 and becomes 20
20.001 rendered as 20.00 and becomes 20

如果您不同意printf的舍入策略,只需使用round()({1}}的{​​副本}并强制使用自己的percentage。或者您也可以使用三位数sprintf(),并删除第三位数。

在您的具体情况下(注意我的系统(Linux x86_64)如何呈现0x419FFFFF):

#include <stdio.h>
#include <string.h>
#include <stdint.h>

int main(int argc, char **argv)
{
        float percentage = 3.1415;
        char buffer[50];

        ((uint32_t *)(&percentage))[0] = 0x419FFFFF;

        sprintf(buffer, "%.2f", percentage);
        char *p = strstr(buffer, ".00");
        if (p) *p = 0x0;
        printf("%.15f rendered as %.2f and becomes %s\n", percentage, percentage, buffer);
        return 0;
}


19.999998092651367 rendered as 20.00 and becomes 20

答案 1 :(得分:0)

如果ceilf(f) == f是一个整数,您可以尝试使用返回floorf(f) == f的{​​{1}}或true,而不是自己计算小数部分。 另一种方法是使用std lib中的f或数学中的modf (float x, float *ipart)

相关问题