在浮点兼容定点的应用时,分辨率的转换很让人头疼,所以有如下的宏方法。对应关系类似 2--0.01--100 ,可以覆盖倍乘、倍除的数值关系。C /* 辅助宏 */ #define LIB_DEC_FACTOR_TOKEN(dp) LIB_DEC_FACTOR_##dp #define LIB_DEC_FACTOR_0 1 #define LIB_DEC_FACTOR_1 10 #define LIB_DEC_FACTOR_2 100 #define LIB_DEC_FACTOR_3 1000 #define LIB_DEC_FACTOR_4 10000 #define LIB_DEC_FACTOR_5 100000 #define LIB_DEC_FACTOR_6 1000000 #define LIB_DEC_FACTOR_7 10000000 #define LIB_DEC_FACTOR_8 100000000 #define LIB_DEC_FACTOR_9 1000000000 #define LIB_DECIMAL_FACTOR(dp) LIB_DEC_FACTOR_TOKEN(dp) #define LIB_DEC_STEP_TOKEN(dp) LIB_DEC_STEP_##dp #define LIB_DEC_STEP_0 1.0f #define LIB_DEC_STEP_1 1e-1f #define LIB_DEC_STEP_2 1e-2f #define LIB_DEC_STEP_3 1e-3f #define LIB_DEC_STEP_4 1e-4f #define LIB_DEC_STEP_5 1e-5f #define LIB_DEC_STEP_6 1e-6f #define LIB_DEC_STEP_7 1e-7f #define LIB_DEC_STEP_8 1e-8f #define LIB_DEC_STEP_9 1e-9f #define LIB_DECIMAL_STEP(dp) LIB_DEC_STEP_TOKEN(dp) /* 统一管理 */ #define RES_DEC_ACVoltage 2 /* 交流电压 */ #define RES_DEC_LoadACCurrent 2 /* 交流电流 */ #define RES_DEC_OutputACFreq 2 /* 交流频率 */ #define RES_DEC_PowerFactors 3 /* 功率因数 */ #define RES_DEC(name) (RES_DEC_##name) /* 小数位数 */ #define RES_FACTOR(name) (LIB_DECIMAL_FACTOR(RES_DEC_##name)) /* 倍数 */ #define RES_STEP(name) (LIB_DECIMAL_STEP(RES_DEC_##name)) /* 小数 */ 使用类似如下Cint a = RES_DEC(ACVoltage); // =2 获得小数位数 int b = RES_FACTOR(ACVoltage); // =100 获得对应倍数系数 int c = RES_STEP(ACVoltage); // =0.01 获得对应小数系数 辅助函数哪怕具有倍数系数,在浮点转为定点数时依然面临四舍五入的小问题。可能可以结合以下函数进行。C#include <stdint.h> #include <limits.h> /** * @brief 浮点值按十进制位缩放并四舍五入后转整型。 * @param value: 期望被转化的浮点值 * @param decimalPlaces: 缩放的小数位数(10^decimalPlaces) * @retval 四舍五入后的缩放结果,超限时按int32范围饱和 */ int32_t LIB_FloatToScaledInt(float value, uint8_t decimalPlaces) { double scale = 1.0; for(uint8_t i = 0; i < decimalPlaces; i++) { scale *= 10.0; } double scaled = (double)value * scale; if(scaled >= 0.0) { scaled += 0.5; } else { scaled -= 0.5; } if(scaled > (double)INT32_MAX) { return INT32_MAX; } if(scaled < (double)INT32_MIN) { return INT32_MIN; } return (int32_t)scaled; } 一个应用示例CSelfACRunSetting[0].ACVoltage = 123.45678; int a = LIB_FloatToScaledInt(SelfACRunSetting[0].ACVoltage, RES_DEC(ACVoltage); // = 12347
一个零开销宏做浮点定点分辨率统一管理
在浮点兼容定点的应用时,分辨率的转换很让人头疼,所以有如下的宏方法。
对应关系类似
2--0.01--100,可以覆盖倍乘、倍除的数值关系。使用类似如下
辅助函数
哪怕具有倍数系数,在浮点转为定点数时依然面临四舍五入的小问题。可能可以结合以下函数进行。
一个应用示例