ありますか より良い 配列を繰り返すよりも短い方法ですか?
int[] arr = new int[] { 1, 2, 3 };
int sum = 0;
for (int i = 0; i < arr.Length; i++)
{
sum += arr[i];
}
明確化:
より良いプライマリとは、よりクリーンなコードを意味しますが、パフォーマンスの改善に関するヒントも歓迎します。 (すでに述べたように、大きな配列を分割します)。
私はキラーのパフォーマンスの改善を探していたわけではありません-この種類のsyntactic sugarはまだ利用できないのではないかと思っただけです。
.NET 3.5(またはそれ以降)およびLINQを使用できる場合は、試してください
int sum = arr.Sum();
はいあります。 .NET 3.5の場合:
int sum = arr.Sum();
Console.WriteLine(sum);
.NET 3.5を使用していない場合、これを行うことができます。
int sum = 0;
Array.ForEach(arr, delegate(int i) { sum += i; });
Console.WriteLine(sum);
LINQの場合:
arr.Sum()
どう定義するかによります。コードをよりきれいに見せたい場合は、他の回答で述べたように.Sum()を使用できます。操作を迅速に実行する必要があり、大きな配列がある場合は、小計に分割して結果を合計することで並列化できます。
上記のforループソリューションの問題の1つは、すべての正の値を持つ次の入力配列では、合計結果が負になることです。
int[] arr = new int[] { Int32.MaxValue, 1 };
int sum = 0;
for (int i = 0; i < arr.Length; i++)
{
sum += arr[i];
}
Console.WriteLine(sum);
正の結果はintデータ型には大きすぎて負の値にオーバーフローするため、合計は-2147483648です。
同じ入力配列の場合、arr.Sum()の提案により、オーバーフロー例外がスローされます。
より堅牢なソリューションは、次のように「合計」にこの場合の「長い」など、より大きなデータ型を使用することです。
int[] arr = new int[] { Int32.MaxValue, 1 };
long sum = 0;
for (int i = 0; i < arr.Length; i++)
{
sum += arr[i];
}
同じ改善は、shortやsbyteなどの他の整数データ型の合計に対しても機能します。 uint、ushort、byteなどの符号なし整数データ型の配列の場合、合計に符号なしlong(ulong)を使用すると、オーバーフロー例外が回避されます。
Forループソリューションは、Linq .Sum()よりも何倍も高速です。
さらに高速に実行するために、HPCsharp nugetパッケージは、これらすべての.Sum()バージョンと、SIMD/SSEバージョンおよびマルチコアパラレルバージョンを実装して、パフォーマンスを何倍も高速化します。
LINQを好まない場合は、foreachループを使用してインデックス不足を回避することをお勧めします。
int[] arr = new int[] { 1, 2, 3 };
int sum = 0;
foreach (var item in arr)
{
sum += item;
}
非常に大きなアレイの場合、マシンの複数のプロセッサ/コアを使用して計算を実行するのに費用がかかる場合があります。
long sum = 0;
var options = new ParallelOptions()
{ MaxDegreeOfParallelism = Environment.ProcessorCount };
Parallel.ForEach(Partitioner.Create(0, arr.Length), options, range =>
{
long localSum = 0;
for (int i = range.Item1; i < range.Item2; i++)
{
localSum += arr[i];
}
Interlocked.Add(ref sum, localSum);
});
また、Aggregate()
拡張メソッドを使用することもできます。
var sum = arr.Aggregate((temp, x) => temp+x);
Foreachを使用するとコードは短くなりますが、JIT最適化がforループ制御式のLengthとの比較を認識した後、おそらく実行時にまったく同じ手順を実行します。
私が使用した私のアプリの1つで:
public class ClassBlock
{
public int[] p;
public int Sum
{
get { int s = 0; Array.ForEach(p, delegate (int i) { s += i; }); return s; }
}
}