3

最初我使用带有浮点数的 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 打印到缓冲区中?

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

4

2 回答 2

6

你的问题是近似问题。

假设百分比为 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's 的舍入策略,请使用round()on (a copy of)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
于 2013-01-24T11:35:07.030 回答
0

您可以尝试使用ceilf(f) == for floorf(f) == fwhich return trueif fis an integer,而不是自己计算小数部分。另一种选择是modf (float x, float *ipart)从标准库或fmod数学中使用

于 2013-01-24T11:27:14.733 回答