简体   繁体   English

如何在C#中对整数数组求和

[英]How to sum up an array of integers in C#

Is there a better shorter way than iterating over the array?有没有比遍历数组 短的方法?

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

clarification:澄清:

Better primary means cleaner code but hints on performance improvement are also welcome.更好的主要意味着更干净的代码,但也欢迎有关性能改进的提示。 (Like already mentioned: splitting large arrays). (就像已经提到的:拆分大数组)。


It's not like I was looking for killer performance improvement - I just wondered if this very kind of syntactic sugar wasn't already available: "There's String.Join - what the heck about int[]?".我并不是在寻找杀手级的性能改进 - 我只是想知道这种语法糖是否已经可用:“有 String.Join - int[] 到底是怎么回事?”。

如果您可以使用 .NET 3.5(或更新版本)和 LINQ,请尝试

int sum = arr.Sum();

Yes there is.就在这里。 With .NET 3.5:使用 .NET 3.5:

int sum = arr.Sum();
Console.WriteLine(sum);

If you're not using .NET 3.5 you could do this:如果您不使用 .NET 3.5,您可以这样做:

int sum = 0;
Array.ForEach(arr, delegate(int i) { sum += i; });
Console.WriteLine(sum);

使用 LINQ:

arr.Sum()

另一种方法是使用Aggregate()扩展方法。

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

It depends on how you define better.这取决于你如何定义更好。 If you want the code to look cleaner, you can use .Sum() as mentioned in other answers.如果您希望代码看起来更简洁,可以使用其他答案中提到的 .Sum() 。 If you want the operation to run quickly and you have a large array, you can make it parallel by breaking it into sub sums and then sum the results.如果您希望操作快速运行并且您有一个大数组,则可以通过将其分解为子和然后对结果求和来使其并行。

For extremely large arrays it may pay off to perform the calculation using more than one processors/cores of the machine.对于非常大的阵列,使用机器的多个处理器/内核执行计算可能是值得的。

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);
});

If you don't prefer LINQ, it is better to use foreach loop to avoid out of index.如果您不喜欢 LINQ,最好使用 foreach 循环来避免索引不足。

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

One problem with the for loop solutions above is that for the following input array with all positive values, the sum result is negative:上述 for 循环解决方案的一个问题是,对于以下所有为正值的输入数组,总和结果为负:

int[] arr = new int[] { Int32.MaxValue, 1 };
int sum = 0;
for (int i = 0; i < arr.Length; i++)
{
    sum += arr[i];
}
Console.WriteLine(sum);

The sum is -2147483648, as the positive result is too big for the int data type and overflows into a negative value.总和为 -2147483648,因为正结果对于 int 数据类型来说太大并且溢出为负值。

For the same input array the arr.Sum() suggestions cause an overflow exception to be thrown.对于相同的输入数组,arr.Sum() 建议会导致抛出溢出异常。

A more robust solution is to use a larger data type, such as a "long" in this case, for the "sum" as follows:一个更健壮的解决方案是使用更大的数据类型,例如在这种情况下的“long”,用于“sum”,如下所示:

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

The same improvement works for summation of other integer data types, such as short, and sbyte.相同的改进适用于其他整数数据类型的求和,例如 short 和 sbyte。 For arrays of unsigned integer data types such as uint, ushort and byte, using an unsigned long (ulong) for the sum avoids the overflow exception.对于 uint、ushort 和 byte 等无符号整数数据类型的数组,使用 unsigned long (ulong) 作为总和可避免溢出异常。

The for loop solution is also many times faster than Linq .Sum() for 循环解决方案也比 Linq .Sum() 快很多倍

To run even faster, HPCsharp nuget package implements all of these .Sum() versions as well as SIMD/SSE versions and multi-core parallel ones, for many times faster performance.为了更快地运行,HPCsharp nuget 包实现了所有这些 .Sum() 版本以及 SIMD/SSE 版本和多核并行版本,以获得更快的性能。

使用 foreach 将是更短的代码,但在 JIT 优化识别出与 for 循环控制表达式中的 Length 的比较之后,可能会在运行时执行完全相同的步骤。

In one of my apps I used :在我使用的其中一个应用程序中:

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

An improvement on Theodor Zoulias's nice multi-core Parallel.ForEach implementation:对 Theodor Zoulias 的多核 Parallel.ForEach 实现的改进:

    public static ulong SumToUlongPar(this uint[] arrayToSum, int startIndex, int length, int degreeOfParallelism = 0)
    {
        var concurrentSums = new ConcurrentBag<ulong>();

        int maxDegreeOfPar = degreeOfParallelism <= 0 ? Environment.ProcessorCount : degreeOfParallelism;
        var options = new ParallelOptions() { MaxDegreeOfParallelism = maxDegreeOfPar };

        Parallel.ForEach(Partitioner.Create(startIndex, startIndex + length), options, range =>
        {
            ulong localSum = 0;
            for (int i = range.Item1; i < range.Item2; i++)
                localSum += arrayToSum[i];
            concurrentSums.Add(localSum);
        });

        ulong sum = 0;
        var sumsArray = concurrentSums.ToArray();
        for (int i = 0; i < sumsArray.Length; i++)
            sum += sumsArray[i];

        return sum;
    }

which works for unsigned integer data types, since C# only support Interlocked.Add() for int and long.它适用于无符号整数数据类型,因为 C# 仅支持 int 和 long 的 Interlocked.Add()。 The above implementation can also be easily modified to support other integer and floating-point data types to do summation in parallel using multiple cores of the CPU.还可以轻松修改上述实现以支持其他整数和浮点数据类型,以使用 CPU 的多个内核并行求和。 It is used in the HPCsharp nuget package.它用于 HPCsharp nuget 包中。

Is there a better shorter way than iterating over the array?是否有比遍历数组 更好的 更短方法?

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

clarification:澄清:

Better primary means cleaner code but hints on performance improvement are also welcome.更好的主键意味着更干净的代码,但也欢迎有关性能改进的提示。 (Like already mentioned: splitting large arrays). (就像已经提到的:拆分大数组)。


It's not like I was looking for killer performance improvement - I just wondered if this very kind of syntactic sugar wasn't already available: "There's String.Join - what the heck about int[]?".并不是我在寻求提高杀手级性能的方法-我只是想知道这种语法糖是否还不可用:“有String.Join-int []到底有什么用?”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM