Gibt es einen besseren kürzeren Weg als das Iterieren über das Array?
int[] arr = new int[] { 1, 2, 3 };
int sum = 0;
for (int i = 0; i < arr.Length; i++)
{
sum += arr[i];
}
Klärung:
Besser primär bedeutet saubereren Code, aber auch Hinweise zur Leistungsverbesserung sind willkommen. (Wie bereits erwähnt: Aufteilen großer Arrays).
Es ist nicht so, dass ich nach einer Verbesserung der Killerleistung gesucht hätte - ich habe mich nur gefragt, ob diese Art von syntaktischem Zucker noch nicht verfügbar ist: "Es gibt String.Join - was zum Teufel ist mit int []?".
Antworten:
Versuchen Sie es, vorausgesetzt, Sie können .NET 3.5 (oder neuer) und LINQ verwenden
quelle
System.OverflowException
wenn das Ergebnis größer ist, als Sie in eine vorzeichenbehaftete 32-Bit-Ganzzahl (dh (2 ^ 31) -1 oder in Englisch ~ 2,1 Milliarden) passen können.int sum = arr.AsParallel().Sum();
Eine schnellere Version, die mehrere Kerne der CPU verwendet. Um zu vermeiden, dassSystem.OverflowException
Sie verwenden könnenlong sum = arr.AsParallel().Sum(x => (long)x);
Für noch schnellere Versionen, die Überlaufausnahmen vermeiden und alle ganzzahligen Datentypen unterstützen und datenparallele SIMD / SSE-Anweisungen verwenden, werfen Sie einen Blick auf das HPCsharp-Nuget-PaketJa da ist. Mit .NET 3.5:
Wenn Sie .NET 3.5 nicht verwenden, können Sie Folgendes tun:
quelle
foreach
Schleife ist in allen Versionen von C # verfügbar.foreach
nur eine Codezeile durch eine andere und ist nicht kürzer. Abgesehen davonforeach
ist a vollkommen in Ordnung und besser lesbar.foreach (int i in arr) sum += i;
Mit LINQ:
quelle
Es hängt davon ab, wie Sie besser definieren. Wenn der Code sauberer aussehen soll, können Sie .Sum () verwenden, wie in anderen Antworten erwähnt. Wenn der Vorgang schnell ausgeführt werden soll und Sie über ein großes Array verfügen, können Sie ihn parallel schalten, indem Sie ihn in Untersummen aufteilen und dann die Ergebnisse summieren.
quelle
Eine Alternative ist auch die Verwendung der
Aggregate()
Erweiterungsmethode.quelle
Wenn Sie LINQ nicht bevorzugen, ist es besser, foreach-Schleife zu verwenden, um einen Indexverlust zu vermeiden.
quelle
Bei extrem großen Arrays kann es sich lohnen, die Berechnung mit mehr als einem Prozessor / Kern der Maschine durchzuführen.
quelle
Ein Problem bei den obigen for-Schleifenlösungen besteht darin, dass für das folgende Eingabearray mit allen positiven Werten das Summenergebnis negativ ist:
Die Summe ist -2147483648, da das positive Ergebnis für den Datentyp int zu groß ist und in einen negativen Wert überläuft.
Für dasselbe Eingabearray führen die Vorschläge von arr.Sum () dazu, dass eine Überlaufausnahme ausgelöst wird.
Eine robustere Lösung besteht darin, einen größeren Datentyp, wie in diesem Fall einen "langen", für die "Summe" wie folgt zu verwenden:
Die gleiche Verbesserung gilt für die Summierung anderer ganzzahliger Datentypen wie Short und Sbyte. Bei Arrays mit vorzeichenlosen ganzzahligen Datentypen wie uint, ushort und byte wird durch die Verwendung eines vorzeichenlosen Long (ulong) für die Summe die Überlaufausnahme vermieden.
Die for-Schleifenlösung ist auch um ein Vielfaches schneller als Linq .Sum ()
Um noch schneller zu laufen, implementiert das HPCsharp-Nuget-Paket alle diese .Sum () -Versionen sowie SIMD / SSE-Versionen und parallele Multi-Core-Versionen für eine um ein Vielfaches schnellere Leistung.
quelle
long sum = arr.Sum(x => (long)x);
die in C # mit Linq gut funktioniert. Es bietet die volle Genauigkeit für die Summierung für alle vorzeichenbehafteten ganzzahligen Datentypen: sbyte, short und int. Es vermeidet auch das Auslösen einer Überlaufausnahme und ist schön kompakt. Es ist nicht so leistungsstark wie die obige for-Schleife, aber die Leistung wird nicht in allen Fällen benötigt.Die Verwendung von foreach wäre kürzerer Code, führt jedoch zur Laufzeit wahrscheinlich genau dieselben Schritte aus, nachdem die JIT-Optimierung den Vergleich mit Length im for-loop-Steuerungsausdruck erkannt hat.
quelle
In einer meiner Apps habe ich verwendet:
quelle
.Aggregate()
Erweiterungsmethode.Eine Verbesserung gegenüber Theodor Zoulias 'netter Multi-Core-Parallel.ForEach-Implementierung:
Dies funktioniert für vorzeichenlose ganzzahlige Datentypen, da C # nur Interlocked.Add () für int und long unterstützt. Die obige Implementierung kann auch leicht modifiziert werden, um andere Ganzzahl- und Gleitkomma-Datentypen zu unterstützen, um eine Summierung parallel unter Verwendung mehrerer Kerne der CPU durchzuführen. Es wird im HPCsharp-Nuget-Paket verwendet.
quelle
Versuchen Sie diesen Code:
Das Ergebnis ist:
quelle