【问题标题】:Cleanest way to convert a float to uint将浮点数转换为 uint 的最简洁方法
【发布时间】:2021-04-24 11:39:08
【问题描述】:

我有一个浮点值,它应该只取 -40 到 +120 之间的值。对于给定的数据传输功能,我需要将其转换为 uint16(或两个 uint8)。将这个有限的十进制范围映射到 uint16 的所有可能值的最简洁方法是什么?

因此,如果浮点数 120,则为 65535,如果在范围内,则只是线性关系(因此增量约为 0.0024)。

【问题讨论】:

  • 16 位整数中的每个值都将对应于161.0 / 65536.0(如您所见,大约为0.0025)。所以首先你需要对输入值进行零偏移(即添加40),然后除以161.0 / 65536.0,得到相应的整数值。无论如何,这就是数学解决方案,但它不会为您提供您可能希望的确切值(-40.0 除外,它确实是0)。
  • @Someprogrammerdude (120.0+40.0) / (161.0/65536) != 65535 根据需要。应该是160.0/65535.0。显然您已经提供了答案 - 为什么将 int 作为评论发布?

标签: c


【解决方案1】:

测试极限(饱和)情况,然后当在范围内时,值为:

(f + 40)/160 * 65535

这只是简单的算术。

uint16_t int_val = 0 ;
if( float_val < -40.0f )
{
    int_val = 0 ;
}
else if( float_val > 120.0f )
{
    int_val = 0xFFFF ;
}
else
{
    int_val = (uint16_t)((float_val + 40.0f) / 160.0f * (float)0xFFFF) ; 
}

【讨论】:

  • 比起简单的演员表,最好使用floorfceilfnearbyintf(或truncfroundflrintf),具体取决于你想如何四舍五入。
  • @SGeorgiades 其中一些选项可能会导致值大于 65535。这不是偏好问题 - 如果您想要对所述要求的有效解决方案,只有一个正确的舍入。不过,还有其他解决方案。您也许应该发布并回答并解释为什么它会被首选。
  • 实际上,@Clifford,这些都不会产生大于 65535 的值,因为您已经测试了边缘情况。并且不只有一种正确的舍入方法;这是一个问题,即舍入后的值是否比真实值略大或略小。
  • @SGeorgiades 同意 - 反思。在计算上这更简单,但峰值量化误差最大。
【解决方案2】:

这是我与上述略有不同的版本:

uint16_t convert(float fval)
{
    if (fval < -40) return(0);
    if (fval > 120) return(UINT16_MAX);
    return(lrintf((fval + 40) / 160 * UINT16_MAX);
}

如果您愿意,可以使用floorfceilf 代替lrintf,具体取决于您的舍入偏好。

请注意,要定义 UINT16_MAX,您必须包含 stdint.h

【讨论】:

  • SO 通过投票/接受来订购答案。引用“以上”的答案可能不成立。
  • 你为什么不想要一个“裸号码”?而且我不知道你所说的“半身裙”是什么意思。
  • return 语句中返回的值不需要括号。 return 0; 就够了。 return(0); 杂乱无章。最后一条语句没有平衡括号。
猜你喜欢
  • 2020-08-06
  • 2011-01-20
  • 1970-01-01
  • 2010-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-08
相关资源
最近更新 更多