web-dev-qa-db-ja.com

C#で整数の配列を合計する方法

ありますか より良い 配列を繰り返すよりも短い方法ですか?

int[] arr = new int[] { 1, 2, 3 };
int sum = 0;
for (int i = 0; i < arr.Length; i++)
{
    sum += arr[i];
}

明確化:

より良いプライマリとは、よりクリーンなコードを意味しますが、パフォーマンスの改善に関するヒントも歓迎します。 (すでに述べたように、大きな配列を分割します)。


私はキラーのパフォーマンスの改善を探していたわけではありません-この種類のsyntactic sugarはまだ利用できないのではないかと思っただけです。

97
Filburt

.NET 3.5(またはそれ以降)およびLINQを使用できる場合は、試してください

int sum = arr.Sum();
163
Tomas Vana

はいあります。 .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);
63
Ahmad Mageed

LINQの場合:

arr.Sum()
20
Chris

どう定義するかによります。コードをよりきれいに見せたい場合は、他の回答で述べたように.Sum()を使用できます。操作を迅速に実行する必要があり、大きな配列がある場合は、小計に分割して結果を合計することで並列化できます。

5
unholysampler

上記の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バージョンおよびマルチコアパラレルバージョンを実装して、パフォーマンスを何倍も高速化します。

2
DragonSpit

LINQを好まない場合は、foreachループを使用してインデックス不足を回避することをお勧めします。

int[] arr = new int[] { 1, 2, 3 };
int sum = 0;
foreach (var item in arr)
{
   sum += item;
}
2
HENG Vongkol

非常に大きなアレイの場合、マシンの複数のプロセッサ/コアを使用して計算を実行するのに費用がかかる場合があります。

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);
});
2
Theodor Zoulias

また、Aggregate()拡張メソッドを使用することもできます。

var sum = arr.Aggregate((temp, x) => temp+x);
1
ja72

Foreachを使用するとコードは短くなりますが、JIT最適化がforループ制御式のLengthとの比較を認識した後、おそらく実行時にまったく同じ手順を実行します。

0
Ben Voigt

私が使用した私のアプリの1つで:

public class ClassBlock
{
    public int[] p;
    public int Sum
    {
        get { int s = 0;  Array.ForEach(p, delegate (int i) { s += i; }); return s; }
    }
}
0
merrais