将 float 转换为 uint8 缓冲区

问题描述

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 缓冲区的大小。

任何有关如何解决此问题的建议将不胜感激。

解决方法

一个简单的方法是:

  1. 再分配一个元素的缓冲区(此处为buffer_buffer
  2. 通过 snprintf() 将浮点数转换为字符串
  3. 将转换结果复制到buffer
#include <stdio.h>
#include <string.h>
#include <inttypes.h>

int main(void) {
    float f = 123.45;
    uint8_t buffer[11];
    char buffer_buffer[12];
    snprintf(buffer_buffer,sizeof(buffer_buffer),"%011.2f",f);
    memcpy(buffer,buffer_buffer,sizeof(buffer));
    for (int i = 0; i < 11; i++) printf(" 0x%02X",buffer[i]);
    putchar('\n');
    return 0;
}

直接使用 snprintf()buffer 效果不佳,因为那里没有终止空字符的空间。

,

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

使用 sprintf() 和朋友将 float 转换为字符串。

诀窍是格式选择。如何在 11 个字节中容纳 float 的范围和精度?

"%f" 对于大值失败。对于较小的值,信息会丢失,因为全部变为“0.0”`。

"%e""%g" 解决了 "% .3E" 的范围问题,因为它打印 sd.dddEsee\0",但可能会失去精度,这可能需要更多(例如常见的 float 最多 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;
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...