Tuesday 24 January 2017

C # Moving Average Warteschlange

Wenn Leistung dieses Codes kritisch ist, dann könnte es sinnvoll sein, Heapzuweisungen für Kerzen zu vermeiden. Ich denke, die vernünftigste Art, dies zu tun, wäre, Candle zu einer Struktur zu machen. Obwohl veränderliche Werttypen sind böse. So würde ich auch Refactor Kerze unveränderlich sein. Dies bedeutet auch, dass sich die Implementierung von newestCandle ändern müsste, wahrscheinlich in ein Paar von Doppelfeldern (oder alternativ eine separate veränderliche und rücksetzbare Klasse). Ich sehe keine andere potenzielle Leistungsproblem in Ihrem Code. Aber wenn es um die Leistung geht, sollten Sie sich immer auf Profiling, nicht Ihre (oder jemand elses) Intuition verlassen. Auch ich mag nicht einige Namen Ihrer Methoden. Speziell: ValueUpdated. Methodennamen sollten in der Regel in der Form etwas tun, nicht etwas passiert. Also ich denke, ein besserer Name wäre UpdateValue. Hinzufügen. Ändern. Dies sind die beiden grundlegenden Operationen Ihres MovingAverage und ich denke, dass diese Namen nicht ausdrücken die Bedeutung gut. Ich würde sie so etwas wie MoveAndSetCurrent und SetCurrent nennen. beziehungsweise. Obwohl diese Benennung bedeutet, dass die grundlegenden Operationen eher Move und SetCurrent sein sollten. Um eine asymptotische Performance von O (n) zu erreichen (wie es die handcodierte Lösung tut), könnten Sie die Aggregate-Funktion wie in The akumulated value (implementiert) verwenden Als anonymer Typ) enthält zwei Felder: Ergebnis enthält die Ergebnisliste bis jetzt aufgebaut. Das Arbeiten enthält die letzten Perioden-1 Elemente. Die Aggregatfunktion fügt den aktuellen Wert der Arbeitsliste hinzu, baut den aktuellen Durchschnitt auf und fügt sie dem Ergebnis hinzu und entfernt dann den ersten (d. H. Ältesten) Wert aus der Arbeitsliste. Das Saatgut (d. h. der Anfangswert für die Akkumulation) wird aufgebaut, indem die ersten Perioden-1-Elemente in die Arbeits-und Initialisierungsergebnis zu einer leeren Liste gebracht werden. Folglich beginnt die Aggregation mit der Elementperiode (durch Überspringen (Perioden-1) - Elemente am Anfang). In der Funktionsprogrammierung ist dies ein typisches Verwendungsmuster für die Aggregat - (oder Falz-) Funktion, btw. Die Lösung ist nicht funktional sauber, da die gleichen Listenobjekte (Arbeit und Ergebnis) in jedem Schritt wiederverwendet werden. Im nicht sicher, wenn das Probleme verursachen könnte, wenn einige zukünftige Übersetzer versuchen, die Aggregate-Funktion automatisch zu parallellisieren (auf der anderen Seite Im auch nicht sicher, ob das möglich ist, nachdem alle.). Eine rein funktionale Lösung sollte bei jedem Schritt neue Listen anlegen. Beachten Sie außerdem, dass C keine leistungsfähigen Listenausdrücke aufweist. In einigen hypothetischen Python-C-gemischten Pseudocode könnte man die Aggregationsfunktion schreiben, die in meiner bescheidenen Meinung ein wenig eleganter wäre :) Beachte die Laufzeit von O (n2). Da Sie bei jedem Schritt immer mehr Elemente überspringen müssen (und afaik Skip (i) I mal IEnumerator. MoveNext aufrufen muss). Siehe meine Antwort für eine Lösung in O (n) Zeit. (Ich habe gerade bemerkt, der OP-Kommentar unten, dass heshe wird möglicherweise die Werte aus einer SQL-DB in der Zukunft. In diesem Fall würde ich jede starke entmutigen von dieser Lösung) ndash MartinStettner Mar 3 11 at 0:53 Für die effizienteste Art und Weise möglich Um einen Moving Average mit LINQ zu berechnen, sollten Sie LINQ nicht verwenden Ich schlage vor, eine Helper-Klasse zu erstellen, die einen gleitenden Durchschnitt auf eine möglichst effiziente Weise berechnet (mit einem kreisförmigen Puffer und einem kausalen gleitenden Durchschnittsfilter) und dann eine Erweiterungsmethode Zu LINQ. First up, der gleitende Durchschnitt Diese Klasse bietet eine sehr schnelle und leichte Implementierung eines MovingAverage-Filters. Es erzeugt einen kreisförmigen Puffer der Länge N und berechnet eine Addition, eine Subtraktion und eine Multiplikation pro angehängten Datenpunkt im Gegensatz zu den N Multiplikations-Adds pro Punkt für die Brute-Force-Implementierung. Die oben genannten Erweiterungsmethoden wickeln die MovingAverage-Klasse und ermöglichen die Einfügung in einen IEnumerable-Stream. Um dies in einer funktionalen Weise zu tun, benötigen Sie eine Scan-Methode, die in Rx, aber nicht in LINQ. Lets schauen, wie es aussehen würde, wenn wed haben eine Scan-Methode Und heres die Scan-Methode, genommen und angepasst von hier: Dies sollte eine bessere Leistung als die Brute-Force-Methode haben, da wir eine laufende Summe verwenden, um die SMA berechnen. Um zu beginnen, müssen wir die erste Periode berechnen, die wir hier Samen nennen. Dann wird jeder nachfolgende Wert aus dem akkumulierten Samenwert berechnet. Dazu benötigen wir den alten Wert (das ist t-delta) und der neueste Wert, für den wir die Serie reihen, einmal von Anfang an und einmal durch das Delta verschoben. Am Ende führen wir einige Bereinigung durch Hinzufügen von Nullen für die Länge der ersten Periode und das Hinzufügen der anfänglichen Seed-Wert. Beantwortet Jun 19 13 am 22:58


No comments:

Post a Comment