将 float 转换为 uint8 缓冲区
Convert float to uint8 buffer
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_buffer
)
- 通过
snprintf()
将浮点数转换为字符串
- 复制转换结果到
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
效果不佳,因为那里没有终止空字符的空间。
I need it's value to be stored in a uint8 buffer as characters.
使用sprintf()
和朋友将float
转换为字符串。
诀窍在于格式选择。如何在 11 个字节中容纳 float
的范围和精度?
"%f"
对大值失败。对于较小的值,信息会丢失,因为全部变为“0.0”`。
"%e"
或 "%g"
解决了 "% .3E"
的范围问题,因为它打印 sd.dddEsee[=18=]"
,但可能会失去精度可能需要更多(例如,常见 float
最多 9 位有效数字)。
"%a"
解决了 "% .3A"
的范围问题,因为打印 0Xsx.xxxPsbb[=22=]
,更好一点(如果可以丢弃前导“0X”),因为十六进制数字携带更多信息, 但指数可能会占用 3 位数。
自适应解决方案。尝试各种岁差和 return 最好的。 snprintf()
将 return [1...10] 成功用于 11 字节缓冲区。
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;
}
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_buffer
) - 通过
snprintf()
将浮点数转换为字符串
- 复制转换结果到
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
效果不佳,因为那里没有终止空字符的空间。
I need it's value to be stored in a uint8 buffer as characters.
使用sprintf()
和朋友将float
转换为字符串。
诀窍在于格式选择。如何在 11 个字节中容纳 float
的范围和精度?
"%f"
对大值失败。对于较小的值,信息会丢失,因为全部变为“0.0”`。
"%e"
或 "%g"
解决了 "% .3E"
的范围问题,因为它打印 sd.dddEsee[=18=]"
,但可能会失去精度可能需要更多(例如,常见 float
最多 9 位有效数字)。
"%a"
解决了 "% .3A"
的范围问题,因为打印 0Xsx.xxxPsbb[=22=]
,更好一点(如果可以丢弃前导“0X”),因为十六进制数字携带更多信息, 但指数可能会占用 3 位数。
自适应解决方案。尝试各种岁差和 return 最好的。 snprintf()
将 return [1...10] 成功用于 11 字节缓冲区。
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;
}