使用NEON指令的好处就是一次可以转4个float到int,但是有个不好处理的事情就是四舍五入。使用
vcvtq_s32_f32是可以转f32到s32,但它是截断的,不会做四舍五入处理。这时候有个小窍门就是对正的浮点数加上0.5f,对负的浮点数减去0.5f,再调用vcvtq_s32_f32就相当于是四舍五入了。
float ftmp[] = {0.5f, -1.0f, 0.49999997f, (1<<23)+1};
float32x4_t inputFloat = vld1q_f32(ftmp);
// 1. 获取浮点数的符号位
int32x4_t reinterpretInt = vreinterpretq_s32_f32(inputFloat);
int32x4_t signExtract = vdupq_n_s32(2147483648);
int32x4_t signSignal = vandq_s32(reinterpretInt, signExtract);
// 2. 将0.49999997f或上符号位
float32x4_t roundValue = vdupq_n_f32(0.49999997f);
float32x4_t plusValue = vreinterpretq_f32_s32(vorrq_s32(vreinterpretq_s32_f32(roundValue), signSignal));
// 3. 加上带符号的0.49999997f
float32x4_t sumValueF = vaddq_f32(inputFloat, plusValue);
// 4. 转换为整数
int32x4_t sumValueInt = vcvtq_s32_f32(sumValueF);
以上代码中为了更准确的处理浮点数,使用了0.49999997f来代替0.5f。因为IEEE 754浮点标准中,float32采用的是1.8.23格式,
对于等于0.49999997f或大于(1<<23)的浮点数,使用加减0.5后转换得到的值会得到不正确的结果。