浮動小数点と固定小数点を併用するアプリケーションでは、スケール(小数桁)の変換がとても面倒です。そこで、次のようなマクロの方法があります。対応関係は 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)) /* 小数 */ 展開 · 38 行コピー 使い方は次のとおりです。Cコピーint 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; } 展開 · 39 行コピー 応用例を次に示します。CコピーSelfACRunSetting[0].ACVoltage = 123.45678; int a = LIB_FloatToScaledInt(SelfACRunSetting[0].ACVoltage, RES_DEC(ACVoltage); // = 12347
浮動小数点/固定小数点のスケールを一元管理するゼロオーバーヘッドマクロ
浮動小数点と固定小数点を併用するアプリケーションでは、スケール(小数桁)の変換がとても面倒です。そこで、次のようなマクロの方法があります。
対応関係は
2--0.01--100のようなもので、倍率の乗算・除算の関係をカバーできます。使い方は次のとおりです。
補助関数
倍率係数があっても、浮動小数点数を固定小数点数に変換する際には、四捨五入の小さな問題が残ります。次のような関数と組み合わせるとよいでしょう。
応用例を次に示します。