C 将浮点转换为uint的最干净的方法

C 将浮点转换为uint的最干净的方法,c,C,我有一个浮点值,应该只取-40和+120之间的值。对于给定的数据传输函数,我需要将其转换为一个uint16(或两个uint8)。将这个有限的十进制范围映射到uint16的所有可能值的最干净的方法是什么 因此,如果浮点数120,则为65535,如果在范围内,则仅为线性关系(因此增量为~0.0024)。测试极限(饱和)情况,如果在范围内,则值为: (f+40)/160*65535 这只是简单的算术 uint16_t int_val = 0 ; if( float_val < -40.0f )

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

因此,如果浮点数<40,uint16值应为0,如果浮点数>120,则为65535,如果在范围内,则仅为线性关系(因此增量为~0.0024)。

测试极限(饱和)情况,如果在范围内,则值为:

(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) ; 
}
uint16\u t int\u val=0;
如果(浮动值<-40.0f)
{
int_val=0;
}
否则如果(浮动值>120.0f)
{
int_val=0xFFFF;
}
其他的
{
int_val=(uint16_t)((浮点值+40.0f)/160.0f*(浮点值)0xFFFF);
}

以下是我对上述内容的略微不同版本:

uint16_t convert(float fval)
{
    if (fval < -40) return(0);
    if (fval > 120) return(UINT16_MAX);
    return(lrintf((fval + 40) / 160 * UINT16_MAX);
}
uint16\u t转换(浮点值)
{
如果(fval<-40)返回(0);
如果(fval>120)返回(UINT16_MAX);
返回值(lrintf((fval+40)/160*UINT16_最大值);
}
如果愿意,您可以使用
floorf
ceilf
而不是
lrintf
,具体取决于您的舍入首选项


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

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作为注释发布?与其使用简单的强制转换,不如使用
floorf
ceilf
nearbyintf
(或
truncf
roundf
,或
lrintf
),这取决于您希望对值进行舍入的方式。@SGeorgiades这些选项中的一些可能会导致值大于65535。这不是偏好的问题-如果您希望对所述的要求有一个有效的解决方案,则只有一个正确的舍入。不过,考虑到这一点,还有其他解决方案。您可能应该发布并回答,并解释原因最好是这样。事实上,@Clifford,所有这些都不会导致值大于65535,因为您已经测试了边缘情况。而且不仅有一种正确的取整方法;问题是取整后的值是略大于还是略小于真实值。@SGeorgiades同意-反思。计算上更简单,但峰值量化误差最大。因此,通过投票/接受来排序答案。参考答案“以上”可能不成立。你为什么不想要一个“裸体数字”?我不知道你所说的“半裸”是什么意思。在
return
语句中返回的值周围不需要括号。
return 0;
足够。
return(0);
杂乱无章。最后一条语句没有平衡的括号。