基于STM32的浮点数运算出错详解

    科技2022-07-13  134

    浮点数分离成整数和小数

    因为十进制运算的底层是2进制运算,有些浮点数并不能完全用二进制表示,一定会有误差,误差在小数点最后几位。

    比如下面这个例子,想要分别取出整数部分和小数部分。浮点数26.90想要得到的理想输出结果是 整数26和整数90 两个数。

    float value = 26.90; unsigned int value_integer; //存放整数 26 unsigned char value_decimal; //存放小数(实际放大了100倍) 90 float decimal_old; //存放小数(未乘以100) float decimal_new; //存放小数(乘以100) value_integer = (unsigned int)value; //取整数 26 decimal_old = value - value_integer; //取小数(未乘以100) decimal_new = decimal * 100.0f; //取小数(乘以100) value_decimal = (unsigned char)decimal_new; //强制类型转换,取出小数部分 90 printf("value = %d",value); printf("value_integer = %d",value_integer); //打印整数部分 printf("decimal_old = %f",decimal_old); //打印小数部分(未乘以100) printf("decimal_new = %f",decimal_new); //打印小数部分(乘以100) printf("value_decimal = %d",value_decimal); //打印左移两位小数点后的小数部分,即实际放大了100倍

    经过实验仿真后,得到的输出结果如下

    value = 26.900000 value_integer = 26 decimal_old = 0.900000 decimal_new = 89.999962 value_decimal = 89

    会发现前后结果不一致,得不到理想的效果:整数26和整数90。因此,需要对浮点数进行一定的处理。

    这里将完整的操作封装成一个函数,供大家使用。

    //函数功能:将浮点数分离成 整数部分和小数部分 //value:待分离的浮点数 //value_integer:指针,用于存放整数部分 //value_decimal:指针,用于存放小数部分 static void Separate_IntegerAndDecimal(float value, unsigned int *value_integer, unsigned char *value_decimal) { float decimal; *value_integer = (unsigned int)value; //取出整数部分 decimal = value - (*value_integer); //小数部分(未处理) *value_decimal = (unsigned char)((decimal * 100.00f) + 0.5f); //取出小数部分(已处理) }

    实验仿真后得到理想的实验结果,分离出整数26和整数90。

    这里特别注意:

    浮点数计算一直计算下去,误差会越大,所以value每次传入的值都是新的(每次传入一个确定的实参浮点数)的话,不会有任何影响(一点都不会有)。

    但是,如果一开始就定义一个变量temp,并且temp一直自加一个浮点数,再把temp作为参数多次传进这个分离整数和小数的函数,那么它的结果误差会越来越大。

    比如下面这个例子

    float temp = 26.90f; unsigned int value_integer; unsigned char value_decimal; while(1) { Separate_IntegerAndDecimal(temp,&value_integer,&value_decimal); printf("value_integer = %d",value_integer); printf("value_decimal = %d",value_decimal); temp += 0.10f; delay_ms(500); }
    Processed: 0.013, SQL: 8