【问题标题】:Convert a float number to char array on C在C上将浮点数转换为char数组
【发布时间】:2020-09-02 00:10:45
【问题描述】:

我正在尝试将浮点数转换为 char 数组。 sprintf() 对我不起作用,dtostrf 也不起作用。 因为我有一个十进制数的限制(它是 5)我试过这个:

    int num = f;
    int decimales = (f-num)*10000;

在我输入数字 123.050 之前一切正常。它没有给我小数部分“0.50”,而是给了我一个 5000,因为现在我的“小数”变量是 int,它不计算 0。

还有其他方法可以转换吗?

【问题讨论】:

  • 你没有浮点数。您有两个 int 值...声明您的浮点数并使用 int chars_reqd = snprintf (NULL, 0, "%.5f", fvalue); 然后分配 chars_reqd + 1 字符或使用固定数组,例如 char floatstr[64];sprintf (floatstr, "%.5f", fvalue);
  • 使用 sprintf(cad,"%.5f", f) 对你也不起作用?
  • (a) 解释为什么sprintf 不适合您。 (b) 完整地解释你想要的输出。小数部分是否应该总是正好有五位数字?最多5个?整数部分有限制吗?非常大(1e300)或非常小(1e-300)的数字呢?负数呢? (c) 10000 乘以 .05 是 500,而不是 5000。您的示例中的错误是 10000、5000 还是其他? (d) 数字是否应该四舍五入或截断为五位小数?舍入或截断中的小错误是否重要?
  • 请确认您需要 4 位小数,正如 10000 所建议的那样。

标签: c floating-point char type-conversion microcontroller


【解决方案1】:

printf() 中使用%04d

 const int D4 = 10000;

 double f = 123.050;
 int i = round(f*D4);
 int num = i / D4;
 int decimales = i % D4;
 printf("%d.%04d\n", num, decimales);

给予

123.0500

如果您担心int 溢出(因为我们将数字乘以10000),请改用longlong long...

在包含前导零的字符串中保存小数

char sdec[5];
sprintf(sdec, "%04d", decimales);

sdec 包含小数,包括前导零。

(另见Is floating point math broken?

【讨论】:

  • 好的.. 但是我的十进制变量有什么方法可以保存前导 0 吗?
  • 这个答案为时过早。关于所需位数、精确格式和所需四舍五入的问题存在错误和遗漏。此外,这个答案很草率:乘以舍入 10000 会引入舍入错误,并且此答案中的代码会截断可能需要舍入的位置。注意(f-num + 0.0000001)会导致小数部分超过1,导致显示不正确。
  • round((f-num)*10000) 将导致 123.99996... 显示为“123.10000”。
  • 这个程序我想要的......通常你想要四舍五入......
  • 否,如果使用舍入,123.99996... 应显示为“124.0000”。 “123.10000”是错误的。
【解决方案2】:

由于嵌入式系统的空间限制,您需要一种快速而肮脏的方法来生成具有浮点数的十进制表示的字符串,而无需链接sprintf。小数位数是固定的。这是一个建议:

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

char *ftoa(char *dest, size_t size, double val, int dec) {
    char *p = dest;
    char *q = dest + size;
    long long mul = 1;
    long long num;
    int i;
    if (size == 0)
        return NULL;
    *--q = '\0';
    if (size == 1)
        goto fail;
    if (val < 0) {
        val = -val;
        if (p >= q)
            goto fail;
        *p++ = '-';
    }
    for (i = 0; i < dec; i++) {
        mul *= 10;
    }
    num = (long long)(val * mul + 0.5);
    for (i = 1; i < dec + 2 || num > 0; i++) {
        if (p >= q)
            goto fail;
        *--q = '0' + (num % 10);
        num = num / 10;
        if (i == dec) {
            if (p >= q)
                goto fail;
            *--q = '.';
        }
    }
    memmove(p, q, dest + size - q);
    return dest;
fail:
    return memset(dest, '*', size - 1);
}

int main(int argc, char *argv[]) {
    char buf[24];

    for (int i = 1; i < argc; i++) {
        double d = strtod(argv[i], NULL);
        int dec = 5;
        if (i + 1 < argc)
            dec = atoi(argv[++i]);
        printf("%s\n", ftoa(buf, sizeof buf, d, dec));
    }
    return 0;
}

【讨论】:

  • val * mul + 0.5 不准确时,num = (long long)(val * mul + 0.5); 可能无法提供最佳结果。
  • @chux-ReinstateMonica:你是对的,上面是解决问题的一个非常简单的方法。一个完整的解决方案至少可以说是不平凡的。我应该用这个函数的限制来完善答案。
猜你喜欢
  • 2021-07-16
  • 2011-02-28
  • 2019-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多