Arduino:float函数返回inf

问题描述 投票:1回答:1

我有一个功能(如下所示),我需要一些建议。该函数返回适合(通过最小二乘法)到n个数据点的线的斜率。为了给你一个背景,我的项目是一个基于气压的高度计,它使用这个功能根据n个最近的高度 - 时间对确定速度。这些高度 - 时间对存储在2个全局数组(times[]alts[])中。

我的问题不是这个方法不起作用。它通常会。但有时我会运行高度计,这个函数会返回值'inf',其中散布着一堆其他错误的值(我也看到'NaN',但这种情况更为罕见)。我现在有一些怀疑的领域,但我想要一个全新的视角。以下是一些可能使用或不使用的上下文信息:

  • 我正在使用中断编码器
  • times[]数组是unsigned long类型
  • alts[]数组是float类型
  • nconst int,在这种情况下n = 9
  • 在ATMEGA328上,doublefloat相同.. Arduino-double float velF() { // uses the last n data points, fits a line to them, // and uses the slope of that line as the velocity at that moment float sumTY = 0, sumT = 0, sumY = 0, sumT2 = 0; for (int i = 0; i < n; i++) { sumTY += (float)times[i] * alts[i] / 1000; sumT += (float)times[i] / 1000; sumY += alts[i]; sumT2 += (float)times[i] * times[i] / 1000000; } return (n*sumTY - sumT*sumY) / (n*sumT2 - sumT*sumT); }

任何帮助或建议将不胜感激!

arduino floating-point least-squares divide-by-zero
1个回答
2
投票

代码肯定是按零除。

由于各种原因,n*sumT2 - sumT*sumT将为零。 @John Bollinger在大多数情况下,除法的顶部(被除数)也将为零,并且返回值为零是可以接受的。

float velF(void) {
     float sumTY = 0, sumT = 0, sumY = 0, sumT2 = 0;
     for (size_t i = 0; i < n; i++) {

         // insure values are reasoable
         assert(alts[i]  >= ALT_MIN  && alts[i]  <= ALT_MAX);
         assert(times[i] >= TIME_MIN && times[i] <= TIME_MAX);

         sumTY += (float)times[i] * alts[i] / 1000;
         sumT += (float)times[i] / 1000;
         sumY += alts[i];
         sumT2 += (float)times[i] * times[i] / 1000000;
     }

     float d = n*sumT2 - sumT*sumT;
     if (d == 0) return 0;
     return (n*sumTY - sumT*sumY) / d;
}

旁注:可以分解分区以提高准确性和速度。建议执行最后一次计算为double

float velF(void) {
     float sumTY = 0, sumT = 0, sumY = 0, sumT2 = 0;
     for (size_t i = 0; i < n; i++) {
         float tf = (float) times[i];
         sumTY += tf * alts[i];
         sumT += tf;
         sumY += alts[i];
         sumT2 += tf * tf;
     }

     double nd = n; 
     double sumTd = sumT; 
     double d = nd*sumT2 - sumTd*sumTd;
     if (d == 0) return 0;
     return (nd*sumTY - sumTd*sumY)*1000 / d;
}
© www.soinside.com 2019 - 2024. All rights reserved.