[英]Integration of values in a buffer with Delphi
接下來是我關於差異的問題:
我現在正在考慮進行集成。 我不能完全理解這一點。 情況是,我周期性地接收一個數據緩沖區,該緩沖區包含多個時間間隔固定的值。 我需要區分它們。 自從我在學校做微積分以來已經很久了....
我想出的是:
procedure IntegrateBuffer(ABuffer: TDoubleDynArray;
var AOutBuffer: TDoubleDynArray;
AVPS: integer);
const
SumSum: double = 0.0;
LastValue: double = NaN;
var
i: integer;
dt, aa, hl, hr: double;
begin
// protect from divide by zero
if (AVPS < 1) then exit;
dt := 1 / AVPS;
for i := 0 to high(ABuffer) do begin
if (i = 0) then begin
if (IsNaN(LastValue)) then begin
hl := ABuffer[0];
hr := ABuffer[0];
end else begin
hl := LastValue;
hr := ABuffer[i];
end;
end else begin
hl := ABuffer[i -1];
hr := ABuffer[i];
end;
aa := 0.5 * dt * (hl + hr);
SumSum := SumSum + aa;
AOutBuffer[i] := SumSum;
end;
// remember the last value for next time
LastValue := ABuffer[high(ABuffer)];
end;
我使用的是梯形規則,hl和hr是梯形的左右高度。 dt是基礎。
AVPS是每秒的值。 一個典型的值在10到100之間。緩沖區的長度通常為500到1000個值。
我用新數據一次又一次地調用緩沖時間,新數據與上一個數據塊是連續的,因此下次將保留該塊的最后一個值。
我做的正確嗎? 即,它將適當地整合價值觀嗎?
謝謝。
您似乎需要測試代碼方面的幫助。 正如評論中所討論的,這里是一個非常簡單的測試。
{$APPTYPE CONSOLE}
uses
SysUtils, Math;
type
TDoubleDynArray = array of Double;
var
SumSum: double;
LastValue: double;
procedure Clear;
begin
SumSum := 0.0;
LastValue := NaN;
end;
procedure IntegrateBuffer(
ABuffer: TDoubleDynArray;
var AOutBuffer: TDoubleDynArray;
AVPS: integer
);
var
i: integer;
dt, aa, hl, hr: double;
begin
// protect from divide by zero
if (AVPS < 1) then exit;
dt := 1 / AVPS;
for i := 0 to high(ABuffer) do begin
if (i = 0) then begin
if (IsNaN(LastValue)) then begin
hl := ABuffer[0];
hr := ABuffer[0];
end else begin
hl := LastValue;
hr := ABuffer[i];
end;
end else begin
hl := ABuffer[i -1];
hr := ABuffer[i];
end;
aa := 0.5 * dt * (hl + hr);
SumSum := SumSum + aa;
AOutBuffer[i] := SumSum;
end;
// remember the last value for next time
LastValue := ABuffer[high(ABuffer)];
end;
var
Buffer: TDoubleDynArray;
OutBuffer: TDoubleDynArray;
begin
// test y = 1 for a single call, expected output = 1, actual output = 2
Clear;
Buffer := TDoubleDynArray.Create(1.0, 1.0);
SetLength(OutBuffer, Length(Buffer));
IntegrateBuffer(Buffer, OutBuffer, 1);
Writeln(OutBuffer[high(OutBuffer)]);
Readln;
end.
我在[0..1]范圍內集成了函數y(x) = 1
。 因此,預期輸出為1,但實際輸出為2。
那怎么了 您可以在調試器中進行處理,但是通過檢查代碼可以很容易地看到它。 您將在第一個樣本上求和一個三角形。 當IsNaN(LastValue)
為true時,則不應對積分作出貢獻。 此時,您尚未覆蓋x軸上的任何距離。
因此,要修復代碼,請嘗試以下操作:
....
if (IsNaN(LastValue)) then begin
hl := 0.0;//no contribution to sum
hr := 0.0;
end else begin
hl := LastValue;
hr := ABuffer[i];
end;
....
這解決了問題。
現在讓我們稍微擴展一下測試,然后測試y(x) = x
:
// test y = x, expected output = 12.5
Clear;
Buffer := TDoubleDynArray.Create(0.0, 1.0, 2.0, 3.0, 4.0, 5.0);
SetLength(OutBuffer, Length(Buffer));
IntegrateBuffer(Buffer, OutBuffer, 1);
Writeln(OutBuffer[high(OutBuffer)]);
所以,看起來不錯。
好吧,多次通話呢:
// test y = x for multiple calls, expected output = 18
Clear;
Buffer := TDoubleDynArray.Create(0.0, 1.0);
SetLength(OutBuffer, Length(Buffer));
IntegrateBuffer(Buffer, OutBuffer, 1);
Buffer := TDoubleDynArray.Create(2.0, 3.0, 4.0, 5.0, 6.0);
SetLength(OutBuffer, Length(Buffer));
IntegrateBuffer(Buffer, OutBuffer, 1);
Writeln(OutBuffer[high(OutBuffer)]);
一次只有一個價值呢?
// test y = x for multiple calls, one value at a time, expected 0.5
Clear;
Buffer := TDoubleDynArray.Create(0.0);
SetLength(OutBuffer, Length(Buffer));
IntegrateBuffer(Buffer, OutBuffer, 1);
Buffer := TDoubleDynArray.Create(1.0);
SetLength(OutBuffer, Length(Buffer));
IntegrateBuffer(Buffer, OutBuffer, 1);
Writeln(OutBuffer[high(OutBuffer)]);
傳遞一個空數組怎么辦?
// test y = x for multiple calls, some empty arrays, expected 0.5
Clear;
Buffer := TDoubleDynArray.Create(0.0);
SetLength(OutBuffer, Length(Buffer));
IntegrateBuffer(Buffer, OutBuffer, 1);
Buffer := nil;
SetLength(OutBuffer, Length(Buffer));
IntegrateBuffer(Buffer, OutBuffer, 1);
Buffer := TDoubleDynArray.Create(1.0);
SetLength(OutBuffer, Length(Buffer));
IntegrateBuffer(Buffer, OutBuffer, 1);
Writeln(OutBuffer[high(OutBuffer)]);
呃,訪問沖突。 如果緩沖區為空,只需在開始時跳過函數即可更好地保護它:
if (AVPS < 1) then exit;
if (Length(ABuffer) = 0) then exit;
好,現在最后一次測試通過了
希望你現在明白了。 我剛剛使用了基於點頭的Writeln
的測試,但是這種測試無法擴展。 為自己准備一個單元測試框架(我推薦DUnitX)並構建適當的測試用例。 這也將迫使您分解代碼,以便對其進行精心設計。 使代碼可測試的通常出乎意料的好處之一是,它通常會導致改進接口的設計。
對於您的下一個問題,我要求您向SSCCE提供測試代碼! ;-)
對代碼的一些注釋:
const
或var
傳遞動態數組。 在您的情況下,您想通過const
傳遞輸入緩沖區。 再次,正如我在上一個問題中所說的那樣,編寫測試以證明代碼,並肉眼檢查。 編寫測試的關鍵是從您可能想到的最簡單的東西開始。 如此簡單,以至於您100%都知道答案。 然后,一旦使它起作用,就將測試擴展到更復雜的情況。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.