映射 [-1,+1] 浮点数到 Q31 定点

Mapping [-1,+1] floats to Q31 fixed-point

我需要将浮点数转换为Q31定点数,Q31表示1个符号位,0位整数部分,31位小数部分。这意味着 Q31 只能表示 [-1,0.9999].

范围内的数字

根据定义,当从浮点数转换为定点数时,会乘以 2ˇN,其中 N 是小数部分的大小,在本例中为 31。

但是,我对这段代码感到困惑,它看起来不正确,但有效:

#define q31_float_to_int(x) ( (int) ( (float)(x)*(float)0x7FFFFFFF ) )

它似乎工作正常。例如:

int a = q31_float_to_int(0.5f); 

给出Hex: 0x40000000,可以。

为什么这里的乘法是2ˇ31 - 1,而不是2ˇ31

上面的代码不是将浮点数转换为定点数的好方法。我猜编写代码的人使用 0x7FFFFFFF 的比例因子来避免输入为 1.0 时的溢出。正确的比例因子是 2^31 而不是 2^31 - 1。请注意,将 float(具有 24 位精度)转换为 Q1.31(具有 31 位精度)时也存在精度问题。考虑在乘法之前使输入数据饱和:

const float Q31_MAX_F =  0x0.FFFFFFp0F;
const float Q31_MIN_F = -1.0F;
float clamped = fmaxf(fminf(input, Q31_MAX_F), Q31_MIN_F);

上面的代码会将 input 限制在 [-1.0, 1.0) 的范围内。常数Q31_MAX_F近似1 - (2 ^ -24),考虑到24位精度,Q31_MIN_F-1。然后你可以将 clamped 乘以 2^31,或者更好,使用 scalbnf, or ldexpf:

int result = (int) scalbnf(clamped, 31);

如果你想四舍五入:

int result = (int) roundf(scalbnf(clamped, 31)));