风过空庭,字句正徐来。
关于关于本站关于我给我点钱
更多时间线友链文件服务wiki
联系写留言发邮件GitHub
© 2024-2026 yono. | RSS 订阅 | 站点地图 | | Stay hungry. Stay foolish.
Powered by Mix Space&
白い
.
| 粤 ICP 备2024284785号-1 |
正在被0人看爆
且听风定,再看句成。
残片纸堆

一个零开销宏做浮点定点分辨率统一管理

w59w
AI·GEN

关键洞察

一个零开销宏做浮点定点分辨率统一管理

  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • 在浮点兼容定点的应用时,分辨率的转换很让人头疼,所以有如下的宏方法。

    对应关系类似 2--0.01--100 ,可以覆盖倍乘、倍除的数值关系。

    
    /* 辅助宏 */
    #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))   /* 小数 */
    

    使用类似如下

    int a = RES_DEC(ACVoltage);    // =2 获得小数位数
    int b = RES_FACTOR(ACVoltage); // =100 获得对应倍数系数
    int c = RES_STEP(ACVoltage);   // =0.01 获得对应小数系数
    

    辅助函数

    哪怕具有倍数系数,在浮点转为定点数时依然面临四舍五入的小问题。可能可以结合以下函数进行。

    #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;
    }
    

    一个应用示例

    SelfACRunSetting[0].ACVoltage = 123.45678;
    
    int a = LIB_FloatToScaledInt(SelfACRunSetting[0].ACVoltage, RES_DEC(ACVoltage); // = 12347