如果整数,则使用sprintf格式化不带小数位的浮点数 [英] Use sprintf to format floats with no decimal places if integer

查看:477
本文介绍了如果整数,则使用sprintf格式化不带小数位的浮点数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最初,我使用的sprintf的浮点数始终使用以下代码:2个小数位:

Originally I was using sprintf with floats always with 2 decimal places using the following code:

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

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

One of the percentage values passed was 0x419FFFFF 20 (debugger view), this printed 20.00 into buffer.

相反,我想在不是整数的情况下显示2个小数位,例如

I would like instead to show 2 decimal places when not an integer, e.g.

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

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

I am currently using the following code:

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.我认为,小数部分的总和最终为(19.99-19)* 100 =99.为什么第一个示例不打印19.99?进入缓冲区?

Now if 0x419FFFFF 20 (debugger view) is passed, fractional part is calculated as 99. I assume then the sum for fractional_part ends up being (19.99 - 19) * 100 = 99. Why then does the first example not print 19.99 into buffer?

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

What is the correct solution for my problem?

推荐答案

您的问题是近似问题.

假设百分比为19.999.然后fractional_part将为99,然后将调用浮点分支.

Suppose that the percentage is 19.999. Then fractional_part would be 99, and the floating point branch would be invoked.

但是打印带有两位小数的19.999会将其四舍五入为20.00,并且是要打印的内容.

But printing 19.999 with two decimals will round it to 20.00, and that is what is printed.

您总是可以使用浮点分支来获得一致的结果,然后在."处截断.如果以'.00'开头.否则,您可能会冒着测试和printf的内部风险的风险.

You could always use the floating point branch, in order to get consistent results, and then truncate at '.' if it comes out with '.00'. Otherwise, you risk your test and printf's internals to be at odds some time.

#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的舍入策略,只需对percentage(的副本)使用round()并强制执行.或者,您也可以使用例如三位数字的sprintf()并擦除第三位数字.

If you don't agree with printf's rounding strategy, just use round() on (a copy of) percentage and force your own. Or you might also, e.g., sprintf() with three digits, and erase the third.

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

And in your specific case (note how my system (Linux x86_64) renders 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

这篇关于如果整数,则使用sprintf格式化不带小数位的浮点数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆