【问题标题】:How to convert a double to a hex / bytes如何将双精度数转换为十六进制/字节
【发布时间】:2018-02-28 16:56:12
【问题描述】:

我需要向物联网发送数据,数据需要以字节为单位

要通过 The Things Network 来回发送数据,您需要使用 字节

一些函数返回一个带 2 个小数的浮点数

23.56 要么 4.32

我很难转换我的浮点数并将其保存到一个变量 uint8_t 我的数据中。我必须找到如何转换我的浮点变量

我有一个这样的循环:

/*
NOTE:
uinit8_t mydata[64];
byte nbMaxCapteurs = 10;
mesMesures[i][mesCapteur[i].idDuCapteur].valeur => this is a float
*/

memset(mydata, 0xFF, 64);
uint8_t * ptr = mydata;
for (byte i = 0; i < nbMaxCapteurs; i++) {
  if (mesCapteur[i].actif) {
    *ptr = mesMesures[i][mesCapteur[i].idDuCapteur].valeur;
    ptr += 15; // How to know the number of step to move the pointer
    if (i < nbCapteurActif + 1) {
      *ptr = 0x2C; // virgule
      ptr += sizeof(char);
    }
  } else {
    *ptr = 0x2C; // virgule pour les capteurs inactifs
    ptr += sizeof(char);
  }
}
*ptr = '00'; // Close \0
ptr += sizeof(char);
printData();

我对这种转换非常陌生。真正的问题在这里:

*ptr = mesMesures[i][mesCapteur[i].idDuCapteur].valeur;

printData 打印这个:

04 FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2C 18 FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2C CB FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2C A8 FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2C

但它至少应该打印这个:

34 2E 33 32 FF FF FF FF FF FF FF FF FF FF FF 2C 18 FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2C CB FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2C A8 FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2C

因为34 2e 33 32 等于 4.32。

我不明白也不知道如何“合并”和转换浮点值。然后你能帮我按照浮动的大小移动指针吗?

我真的被这个话题所困扰,非常感谢您的帮助。

【问题讨论】:

  • 您认为uint8_t 可以代表多少个不同的值?小数点分隔符前后两位小数各有多少个值?
  • uint8_t 只有 8 位,所以只有 256 个可能的值。 1 位 + 2 位小数的 double 有 1000 个可能的值,所以这是不可能的。
  • 您只是在问如何将数字四舍五入到小数点后两位吗?还是您真的要求将其放在uint8_t 中?
  • ((int)(luminosity * 100))/100.0 应该为你做这件事
  • "我猜 uint8 不保留小数点"。好吧,对于初学者来说,这是一个integer。根据定义,它没有小数。

标签: arduino hex byte uint8t arduino-c++


【解决方案1】:
  • 如果要在小数点后两位四舍五入,可以使用以下方法:

    double lum = ((int)(luminosity * 100))/100.0;
    
  • 如果要在小数点后两位四舍五入到最接近(从零四舍五入),可以使用以下方法:

    #include <math.h>
    double lum = round(luminosity * 100)/100.0;
    

  • 另一方面,如果您想尽可能高效地将亮度存储为 8 位,则可以使用以下算法。

    uint8_t packed_luminosity;
    if (luminosity >= MAX_LUMINOSITY)       // Just in case
       packed_luminosity = 255;
    else if (luminosity <= MIN_LUMINOSITY)  // Just in case
       packed_luminosity = 0;
    else
       packed_luminosity = (uint8_t)(
           ( luminosity - MIN_LUMINOSITY ) / ( MAX_LUMINOSITY - MIN_LUMINOSITY + 1 ) * 256 );
    

    您可以对这种格式的亮度进行比较和某些操作。

  • 另一种将十进制数打包成整数的方法是定点数。这可以通过在编写程序时为所有亮度选择比例来实现。以下是一些缩放支持的范围:

    uint8_t
    =======
    Scaling  Supported range (binary)         Supported range (decimal)
    -------  -------------------------------  -----------------------------------------
    ...
    B8       [00000000.    .. 111111110.   ]  [0 .. 512)  No odd numbers
    B7       [ 0000000.    ..  11111111.   ]  [0 .. 256)  No decimals
    B6       [  000000.0   ..   1111111.1  ]  [0 .. 128)  .0, .5
    B5       [   00000.00  ..    111111.11 ]  [0 ..  64)  .0, .25, .5, .75
    B4       [    0000.000 ..     11111.111]  [0 ..  32)  Almost one full decimal place
    ...
    
    int8_t
    ======
    Scaling  Supported range (binary)        Supported range (decimal)
    -------  ------------------------------  --------------------------------------------
    ...
    B8       [10000000.   .. 011111110.   ]  [-256 .. 256)  No odd numbers
    B7       [ 1000000.   ..  01111111.   ]  [-128 .. 128)  No decimals
    B6       [  100000.0  ..   0111111.1  ]  [ -64 ..  64)  .0, .5
    B5       [   10000.00 ..    011111.11 ]  [ -32 ..  32)  .0, .25, .5, .75
    B4       [    1000.000 ..    01111.111]  [ -16 ..  16)  Almost one full decimal place
    ...
    

    如您所见,仅使用 8 位是非常有限的,并且您无法像之前的方法那样灵活地选择范围。定点数的优点是您可以对它们执行算术函数(加法、减法、乘法和除法)。

【讨论】:

  • C11 标准草案 n1570:6.3 转换 6.3.1.4 实数浮点数和整数 1 当实数浮点数类型的有限值转换为 _Bool 以外的整数类型时,小数部分被丢弃(即,该值被截断为零)。注意这里的“截断”而不是“舍入”。
  • OP 不想截断;结果应该仍然有小数位。
【解决方案2】:

(我对Arduino一无所知)

让您接近目标的最小变化是:

double luminosity;
uint32_t lum;
lum = (uint32_t)(luminosity * 100);

现在,lum 将包含您的值乘以 100,四舍五入。

您将获得 2345 而不是 23.45。使用 uint8_t 会限制您太多,因为范围太小 (0-255)。你是否有 uint16_t 和 uint32_t 可用,我不知道。

这种技术称为定点算法。

【讨论】:

  • arduino 使用 8 位微型和 32 位算法对它来说有点太贵了。我认为 uint16_t 就足够了(32 位整数的乘法和除法几乎与浮点运算一样昂贵)
猜你喜欢
  • 1970-01-01
  • 2019-08-13
  • 1970-01-01
  • 2014-05-05
  • 1970-01-01
  • 2014-02-07
  • 2022-07-21
  • 2011-04-03
  • 2019-08-31
相关资源
最近更新 更多