如何在 C 中将浮点数转换为 4 字节字符?

问题描述 投票:0回答:3

我想将浮点数(例如 2.45)转换为 4 字节字符数组。 所以 2.45 应该看起来像这样

'@' 'FS' 'Ì' 'Í'
是二进制的 ieee 表示形式
我已经解决了这个问题,但它的复杂性很差。你有什么好的想法吗?

谢谢你的好答案。

你能告诉我从字符数组到浮点数的返回方式吗?

只需使用 memcpy:
c char type-conversion
3个回答
13
投票
2.45 = 01000000 00011100 11001100 11001101

如果您需要相反的字节顺序,那么之后反转
#include <string.h>

float f = 2.45f;
char a[sizeof(float)];

memcpy(a, &f, sizeof(float));
中的字节是一件微不足道的事情,例如

a

你有几种方法可以做到这一点,包括这两种:

10
投票

使用类型转换和指针:
  1. 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; }

    请注意,这在任何方面都不安全,并且“字符串”之后没有字符串终止符。
    
    

    使用
  2. float f = 2.45; char *s = (char *) &f;
  3. union

    现在可以访问 char 数组以获取字节值。另请注意,与第一个替代方案一样,没有字符串终止符。
    
    

可以使用类型转换和指针将 float 转换为 char,如下所示:

0
投票
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

© www.soinside.com 2019 - 2024. All rights reserved.