C 将浮点转换为uint8缓冲区

C 将浮点转换为uint8缓冲区,c,floating-point,type-conversion,uint8t,C,Floating Point,Type Conversion,Uint8t,A有一个float变量,我需要将它的值作为字符存储在uint8缓冲区中。更确切地说,考虑到这样的情况 float f = 123.45 uint8_t buffer[11]; memset(buffer, 0x30, sizeof(buffer)); // I set it at 0x30 because it is character '0' 在此示例中,我的缓冲区需要获取以下值: 0x30 0x30 0x30 0x30 0x30 0x31 0x32 0x33 0x2E 0x34 0x

A有一个
float
变量,我需要将它的值作为字符存储在
uint8
缓冲区中。更确切地说,考虑到这样的情况

float f = 123.45
uint8_t buffer[11];
memset(buffer, 0x30, sizeof(buffer));   // I set it at 0x30 because it is character '0' 
在此示例中,我的缓冲区需要获取以下值:

0x30 0x30 0x30 0x30 0x30 0x31 0x32 0x33 0x2E 0x34 0x35   // 0x2E is the character '.'
不幸的是,我需要以这种方式将其与现有功能集成,因此无法绕过大小
11
缓冲区

任何关于如何进行此项工作的建议都将不胜感激。

一个简单的方法是:

  • 为缓冲区再分配一个元素(
    buffer\u buffer
    此处)
  • 通过将浮点转换为字符串
  • 将转换结果复制到
    缓冲区
  • #包括
    #包括
    #包括
    内部主(空){
    浮点数f=123.45;
    uint8_t缓冲器[11];
    字符缓冲区\ U缓冲区[12];
    snprintf(buffer\u buffer,sizeof(buffer\u buffer),“%011.2f”,f);
    memcpy(buffer,buffer_buffer,sizeof(buffer));
    对于(inti=0;i<11;i++)printf(“0x%02X”,缓冲区[i]);
    putchar('\n');
    返回0;
    }
    
    直接使用
    snprintf()
    buffer
    将不能很好地工作,因为那里没有终止空字符的空间

    我需要它的值作为字符存储在uint8缓冲区中

    使用
    sprintf()
    和friends将
    float
    转换为字符串

    诀窍在于格式选择。如何在11个字节内适应
    浮点
    的范围和精度

    “%f”
    对于较大的值失败。对于较小的值,当所有值都变为“0.0”时,信息将丢失

    %e“
    %g”
    解决了打印
    sd.dddEsee\0”
    时使用
    的%.3E“的范围问题,但可能会丢失精度,这可能需要更多精度(例如,普通
    浮点数最多9个有效数字)

    “%a”
    解决了
    “%.3A”
    的范围问题,因为它打印的
    0Xsx.xxxPsbb\0
    稍微好一点(如果可以丢弃前导的“0X”),因为十六进制数字携带更多信息,但指数可能会侵入3位数字


    自适应解决方案。尝试各种方法并返回可用的最佳值。
    snprintf()
    如果11字节缓冲区成功,将返回[1…10]

     char *print_float(size_t sz, char buffer[sz], float f) {
       for (int p = sz - 1; p >= 0; p--)
         int length = snprintf(buffer, sz, "%.*g", p, f);
         if (length > 0 && (unsigned) length < size) {
           return buffer;
         }
       }
       buffer[0] = 0;
       return buffer;
    }
    
    char*print\u float(大小为sz,字符缓冲区[sz],浮点f){
    对于(int p=sz-1;p>=0;p--)
    int length=snprintf(缓冲区,sz,'%g',p,f);
    如果(长度>0&(无符号)长度<大小){
    返回缓冲区;
    }
    }
    缓冲区[0]=0;
    返回缓冲区;
    }
    
    浮点数的十进制文本表示形式可以使用
    *printf
    函数系列获得,例如
    snprintf
    我将其设置为0x30,因为它是字符“0”不,不是。字符
    '0'
    是字符
    '0'
    。所有使用
    0x30
    的操作都会使事情变得混乱。@Andrew Henle,T他们解释了为什么
    0x30
    被用于
    0
    //@andrei filip,Andrew说的是
    '0'
    更清晰,100%等同于
    0x30
    (好吧,除非你使用的是EBCDIC系统)。鉴于这是一个嵌入式系统,因此可能资源受限,您不能使用
    stdio.h
    函数。取决于您的MCU是否实际有FPU,首先使用浮点可能没有意义。那么更具体地说,这是用于什么系统?@Andreiflip好的,它相当受限于Cortex M0+你不应该在MCU上使用软件浮点或<代码> Stdio.H./Case>函数,它们会占用你所有的内存。请相信我,我现在使用的是同一个MCU,我有20年的嵌入式系统编程经验。四元,然后解析出整数和小数部分,存储在两个整数中,分别将它们转换为ASCII。这比软件浮点和stdio.h的效率大约高100倍。谢谢。这是一个PC解决方案。然而,
    stdio.h
    通常从不在(低端)嵌入式系统中使用。
    %011.2f“
    在处理负数和大正数时会遇到问题。
     char *print_float(size_t sz, char buffer[sz], float f) {
       for (int p = sz - 1; p >= 0; p--)
         int length = snprintf(buffer, sz, "%.*g", p, f);
         if (length > 0 && (unsigned) length < size) {
           return buffer;
         }
       }
       buffer[0] = 0;
       return buffer;
    }