Delphi中缓冲区的差异化

4

我定期接收一段数据缓冲区,其中包含一些按固定时间间隔分离的数值。我需要对它们进行区别。自从我在学校学过微积分以来已经很久了...

我想出的方法是这样的:

function DifferentiateBuffer(
  ABuffer: TDoubleDynArray; AVPS: integer): TDoubleDynArray;
var
  i: integer;
  dt, dy: double;
begin
  if (AVPS = 0) then exit;

  // calc the delta time
  dt := 1 / AVPS;

  // run through the whole buffer
  for i := 0 to high(ABuffer) do begin
    if (i = 0) then
      if (IsNan(FLastDiffValue) = false) then
        dy := ABuffer[0] - FLastDiffValue
      else
        dy := ABuffer[0]
    else
      dy := Abuffer[i] - ABuffer[i -1];

    result[i] := dy / dt
  end;

  // remember the last value for next time
  FLastDiffValue := ABuffer[high(ABuffer)];
end;

AVPS指的是每秒值。这个值通常在10到100之间。缓冲区的长度通常为500到1000个值。

我会不断地使用新数据调用缓冲区,这些数据与前一个数据块连续,因此保留上一块的最后一个值以便下一次使用。在构造函数中,将该最后一个值设置为NAN。

我的做法正确吗?也就是说,它能正确地区分这些值吗?

我还需要整合类似的数据……那会是什么样子呢?


1
如果您将FLastDiffValue初始化为零,则无需检查它是否为NaN。 您可以无条件设置dy:=ABuffer [0] - FLastDiffValue - Rob Kennedy
谢谢,Rob。问题是零可能相差甚远。我考虑过取前三或五个值的平均值,并将其用作第一个值,这比零更好猜测,但仍需要测试。我可能会这样做,但跳过第一个值似乎也是一个不错的解决方案。 - user745323
1个回答

4

我找不到任何问题。

在第一次调用时返回的第一个值将是基于信号以零开始的假设的(ABuffer[0] - 0.0) / dt。我想这就是你的意图。

现在,你可以自己更好地验证代码,而不是要求Stack Overflow社区检查你的代码。你应该使用单元测试框架(例如DUnitX)来测试代码以证明其准确性。输入你能够预测输出结果的函数值。例如,将它输入y = x2或y = sin(x)中的值。

编写测试的另一个巨大好处是它们可以反复执行。当你开发代码时,可能会引入错误。代码今天可能是正确的,但是谁知道在明天进行修改后它仍然会是正确的。如果你有一个强大的测试,就可以防范在维护期间引入的错误。

关于风格的一个注释是:你永远不应该测试= false= true。if语句操作布尔表达式,因此与布尔值进行比较总是相当无意义的。我会像这样编写你的测试:

if not IsNan(FLastDiffValue) then
  dy := ABuffer[0] - FLastDiffValue
else
  dy := ABuffer[0]

或者像这样:
if IsNan(FLastDiffValue) then
  dy := ABuffer[0]
else
  dy := ABuffer[0] - FLastDiffValue

谢谢David,感谢您对如何测试它的建议。关于我的布尔测试风格,我经常使用“condition = false”而不是“not condition”,因为这样读起来更好 - 也就是说,当我阅读代码时更容易理解。我很少甚至从不使用“= true”。您能否展示(伪代码中)集成可能看起来像什么? - user745323
你在这里干什么,写PID控制器吗?不管怎样,看起来你不需要我来教你如何进行积分。你已经成功地完成了微分,那么积分也应该没问题。编写一些好的测试用例,你就会做得很好。具体如何进行积分取决于算法选择。梯形法、辛普森法、高阶方法都可以。其中梯形法最简单。你可以使用与差分方法几乎相同的函数设计,只需将梯形面积相加即可,而不是进行有限差分。一旦你开始测试的常规工作,你会发现编写和验证代码变得容易了许多。 - David Heffernan
我正在转换速度和加速度数据。感谢鼓励和建议。我可以想象梯形法是什么,所以我会先尝试一下。 - user745323
请查看以下维基页面:http://en.wikipedia.org/wiki/Trapezium_Rule http://en.wikipedia.org/wiki/Simpson's_rule 我还要重申一下关于测试的话。编写测试是让你在编码时取得进展的关键。我已经花了整整一周的时间来编写测试。这样做非常棒。最后,我可以写出大量的代码! - David Heffernan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接