Floating point 如何在C中将浮点转换为16位有符号整数分数?

Floating point 如何在C中将浮点转换为16位有符号整数分数?,floating-point,data-conversion,short,Floating Point,Data Conversion,Short,我正在使用NXP为他们的Arm M4F提供的库中的宏,将浮点型变量转换为名为frac16_t的库数据类型,当浮点值小于-1时,该宏不起作用。frac16_t被类型定义为有符号的空头 宏代码为: #定义FRAC16(x)((FRAC16_t)((x)=-1?(x)*0x8000:0x8000:0x7fff)) 此宏的预期行为是将-1和+1之间的任何浮点值转换为16符号整数,表示从-1到(1-1/2^15)的范围,其中0x8000为-1值,0x7fff为接近1的值。如果浮点值大于(接近)1,则结果在

我正在使用NXP为他们的Arm M4F提供的库中的宏,将浮点型变量转换为名为frac16_t的库数据类型,当浮点值小于-1时,该宏不起作用。frac16_t被类型定义为有符号的空头

宏代码为:

#定义FRAC16(x)((FRAC16_t)((x)<0.99996482421875?((x)>=-1?(x)*0x8000:0x8000:0x7fff))

此宏的预期行为是将-1和+1之间的任何浮点值转换为16符号整数,表示从-1到(1-1/2^15)的范围,其中0x8000为-1值,0x7fff为接近1的值。如果浮点值大于(接近)1,则结果在0x7fff处饱和,当浮点值小于-1时,结果应为0x8000

实际发生的情况是,对于小于-1的任何输入,结果为0x7fff(即接近1),对于任何其他值,其效果与公布的一样

我确实发现将0x8000常量强制转换为frac16_t类型可以使宏正常工作,但我不理解为什么原始库宏不工作。将常量更改为-32768同样有效,这两种修复都会导致常量被编码为32位长,这就要求从加载指令附近的闪存中的某个位置间接加载该值,而不是作为指令的一部分的16位文本加载该值

这两种修复都会导致常量被编码为32位长,这需要从闪存中的某个位置间接加载该值

不完全是。十六进制常量转换为双精度,之后转换为有符号短距离

首先使用
测试?some_type_A:some_type_B
,结果是一个公共类型。在这种情况下,
double

(x)*0x8000
是一个
双精度
(或
浮点
),然后
:0x8000
:0x7fff
也成为相同的浮点类型

0x8000
成为32768.0。将超出范围的
double
分配给
signed short
是UB。
常见UB超出最小/最大限值的范围。
在OP的情况下,
double
32768.0变为
signed short
32767

#define FRAC16(x) \\
    ((frac16_t)((x) < 0.999969482421875 ? ((x) >= -1 ? (x)*0x8000 : 0x8000) : 0x7fff))
//                                                                  ^^^^^^    
//                                                                  32768.0


如果要使用
SHRT\u MIN
编码,不要使用
0x8000
,使用
SHRT\u MIN
(-0x7fff-1)

实际发生的情况是,对于小于-1的任何输入,结果都是0x7fff(即接近1),对于任何其他值,它都像广告一样工作。。。正如您前面所说的,对-1和1之间的值进行处理不是唯一的“广告”:此宏的预期行为是将-1和+1之间的任何浮点值转换为。。。?顺便说一句,它也不适用于大于1的值(如上所述)。宏假定分母为0x8000,由于它将值限制为16位有符号数,因此输入值限制为-1到1。否则,结果将超过16位。不要认为0x8000是-32768。它是32768。潜伏者:FWIW,我发布的“定义行为”包括输入超出-1到+1范围时的结果(0x7fff表示输入大于1,0x8000表示输入小于-1)所有这些都适合于短int。对于-1到+1的行为并不是唯一的要求。看起来问题的关键在于编译器将0x8000视为+32768,加上缺少可以将负16位值加载到32位寄存器中的单个Thumb指令。
#define FRAC16(x)
    ((frac16_t)((x) < 0.999969482421875 ? ((x) >= -1 ? (x)*0x8000 : -32768 : 0x7fff))
//                                                                  ^^^^^^^
//                                                                  -32768.0