STM32浮点数计算错误

时间:2019-05-03 10:52:00

标签: c stm32 floating

我必须使用STM32的距离传感器的测量结果来计算2个浮点数。通过以下等式进行计算;

  

结果=(df-ds)/ ds * 10000;

其中df是第一次测量,ds是第二次测量。

方程式的样本值;

  

df = 26.6810;   ds = 25.3270;

我的问题是,这些值的STM32结果为 534.578247 ,但是当我在Windows计算器上手动进行计算时,得到的结果却是 534.607336 ,这与STM32的计算。我还使用了一个手动计算器,并且手动计算器与计算机给出的结果完全相同。

所有变量在程序中都声明为float。 为什么两个计算之间有如此大的差异? 为了使STM32产生更精确的结果,我可以进行哪些更改?

在此先感谢您的帮助。

编辑:我正在使用的代码如下;

 float result= 0;
 dmbres = 27.4587;
   int main()
   {
   while(1)
   {
   result= (float)((dmbres- res)/res)*10000;
   dmbres = res;
   sprintf(datapackage, "%d;%.4f;%.6f\r\n", mid, res,result);
   monitor(datapackage);
   }

数据包包含我需要从MCU接收的其他2条信息,它们与结果计算无关。

我正在使用STM32F407 DISC-1开发板。

2 个答案:

答案 0 :(得分:1)

您具有以下代码:

 float result= 0;
 dmbres = 27.4587;
   int main()
   {
   while(1)
   {
   result= (float)((dmbres- res)/res)*10000;
   dmbres = res;
   sprintf(datapackage, "%d;%.4f;%.6f\r\n", mid, res,result);
   monitor(datapackage);
   }

您给出了以下等式:

  

结果=(df-ds)/ ds * 10000;

具有以下值:

  

df = 26.6810; ds = 25.3270;

您报告了以下结果:

  

结果= 534.578247

我假设以下情况:

  1. df 26.6810 )显示的值来自变量res到字符串的转换:

    sprintf(datapackage, "%d;%.4f;%.6f\r\n", mid, res,result);
    

    由于此输出字符串将四舍五入到小数点后四位,因此它来自的float res值可以是 26.680950164794921875 26.6810474395751953125 。这将为循环的下一次迭代形成dmbres值。

  2. ds 25.3270 )显示的值来自在循环的下一次迭代中将变量res转换为字符串。由于此输出字符串也被四舍五入到小数点后四位,因此它来自的float res值可以是 25.3269500732421875 25.3270473480224609375 范围内的任何值。

  3. result 534.578247 )显示的值来自变量result到字符串的转换,

    sprintf(datapackage, "%d;%.4f;%.6f\r\n", mid, res,result);
    

    此输出字符串对于float非常精确。最接近的存储值为 534.5782470703125

对于dfds的可能值,result = (df-ds)/ds*10000的最小可能值由(26.680950164794921875-25.3270473480224609375)/ 25.3270473480224609375 * 10000 给出,并且(26.6810474395751953125-25.3269500732421875)/ 25.3269500732421875 * 10000 给出了最大值。

从这两个表达式得出的最接近的float值分别为 534.5679931640625 534.6468505859375 。您的 534.5782470703125 的实际结果在此范围内,因此并不意外。

答案 1 :(得分:0)

正如其他人所提到的,数字“太接近”。 32位浮点数使用23位作为有效位,因此仅约7个有效十进制数字。例如1234567。您可以将小数点放在任何地方,但7以后的任何数字都不精确,尤其是在使用它们执行计算之后。 64位double使用52位,并保留约16个十进制数字。

因此您可以将变量声明为double。这样可以为您提供更大的精度范围,但执行速度会慢得多。