我想将浮点数(例如 2.45)转换为 4 字节字符数组。 所以 2.45 应该看起来像这样
'@' 'FS' 'Ì' 'Í'
是二进制的 ieee 表示形式
我已经解决了这个问题,但它的复杂性很差。你有什么好的想法吗?谢谢你的好答案。
你能告诉我从字符数组到浮点数的返回方式吗?
只需使用 memcpy:
2.45 = 01000000 00011100 11001100 11001101
如果您需要相反的字节顺序,那么之后反转
#include <string.h>
float f = 2.45f;
char a[sizeof(float)];
memcpy(a, &f, sizeof(float));
中的字节是一件微不足道的事情,例如
a
你有几种方法可以做到这一点,包括这两种:int i, j;
for (i = 0, j = sizeof(float) - 1; i < j; ++i, --j)
{
char temp = a[i];
a[i] = a[j];
a[j] = temp;
}
请注意,这在任何方面都不安全,并且“字符串”之后没有字符串终止符。 使用
float f = 2.45;
char *s = (char *) &f;
union
现在可以访问 char 数组以获取字节值。另请注意,与第一个替代方案一样,没有字符串终止符。
union u
{
float f;
char s[sizeof float];
};
union u foo;
foo.f = 2.45;
请注意,上面没有
float t= -2.63646464;
char *float2CharArr;
float2CharArr = (char*) &t;
字符串终止符。要追加它,可以这样做,例如,像这样:
\0
使用下面的代码可以实现将浮点值转换为 char 字符串的另一种更精细的方法:char* tmp = realloc(float2CharArr, sizeof(*float2CharArr)+1);
tmp[sizeof(*float2CharArr)+1] = '\0';
float2CharArr=tmp;
下面是如何使用Arduino Studio和相关编码平台进行MCU编程的例子:
union int32_Float_t
{
int32_t Long;
float Float;
};
#ifndef HUGE_VALF
#define HUGE_VALF (__builtin_huge_valf())
#endif
#ifndef FLT_MIN_EXP
#define FLT_MIN_EXP (-999)
#endif
#ifndef FLT_MAX_EXP
#define FLT_MAX_EXP (999)
#endif
#define _FTOA_TOO_LARGE -2 // |input| > 2147483520
#define _FTOA_TOO_SMALL -1 // |input| < 0.0000001
//precision 0-9
#define PRECISION 7
//_ftoa function
void _ftoa(float f, char *p, int *status)
{
int32_t mantissa, int_part, frac_part;
int16_t exp2;
int32_Float_t x;
*status = 0;
if (f == 0.0)
{
*p++ = '0';
*p++ = '.';
*p++ = '0';
*p = 0;
return;
}
x.Float = f;
exp2 = (unsigned char)(x.Long>>23) - 127;
mantissa = (x.Long&0xFFFFFF) | 0x800000;
frac_part = 0;
int_part = 0;
if (exp2 >= 31)
{
*status = _FTOA_TOO_LARGE;
return;
}
else if (exp2 < -23)
{
*status = _FTOA_TOO_SMALL;
return;
}
else if (exp2 >= 23)
{
int_part = mantissa<<(exp2 - 23);
}
else if (exp2 >= 0)
{
int_part = mantissa>>(23 - exp2);
frac_part = (mantissa<<(exp2 + 1))&0xFFFFFF;
}
else
{
//if (exp2 < 0)
frac_part = (mantissa&0xFFFFFF)>>-(exp2 + 1);
}
if (x.Long < 0)
*p++ = '-';
if (int_part == 0)
*p++ = '0';
else
{
ltoa(int_part, p, 10);
while (*p)
p++;
}
*p++ = '.';
if (frac_part == 0)
*p++ = '0';
else
{
char m;
for (m=0; m<PRECISION; m++)
{
//frac_part *= 10;
frac_part = (frac_part<<3) + (frac_part<<1);
*p++ = (frac_part>>24) + '0';
frac_part &= 0xFFFFFF;
}
//delete ending zeroes
for (--p; p[0] == '0' && p[-1] != '.'; --p)
;
++p;
}
*p = 0;
}
此源代码在互联网上的各个地方发布,大多没有署名。例如
这里和
这里。所以归功于匿名作者。 要查看此代码在 .ino 草图上的工作,请查看此 GitHub 存储库 https://github.com/aeonSolutions/aeonlabs-ESP32-C-Base-Firmware-Libraries