Answers:
如果您可以使用.NET 3.5(或更高版本)和LINQ,请尝试
int sum = arr.Sum();
System.OverflowException
如果结果大于您可以使用带符号的32位整数(即(2 ^ 31)-1或英语〜21亿),则将产生错误。
int sum = arr.AsParallel().Sum();
使用多个CPU内核的更快版本。要避免System.OverflowException
使用long sum = arr.AsParallel().Sum(x => (long)x);
,请使用HPCsharp nuget软件包
就在这里。使用.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);
foreach
循环在所有C#版本中均可用。
foreach
刚刚替换一行代码为另一个,而不是更短。除此之外,a foreach
非常好并且更具可读性。
foreach (int i in arr) sum += i;
这取决于您如何定义更好。如果您希望代码看起来更简洁,则可以使用其他答案中提到的.Sum()。如果您希望该操作快速运行并且有一个大数组,则可以将其分解为多个和,然后对其求和,以使其并行。
另一种选择是使用Aggregate()
扩展方法。
var sum = arr.Aggregate((temp, x) => temp+x);
对于非常大的阵列,可能需要使用不止一个机器的处理器/内核来执行计算。
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);
});
上面的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);
总和为-2147483648,因为对于int数据类型,正数太大,并且溢出为负数。
对于相同的输入数组,arr.Sum()建议会导致引发溢出异常。
一种更可靠的解决方案是对“ sum”使用更大的数据类型,例如“ long”(在这种情况下),如下所示:
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版本和多核并行版本,从而使性能提高了许多倍。
long sum = arr.Sum(x => (long)x);
即使用Linq在C#中可以很好地工作。它为所有带符号整数数据类型的总和提供了完全准确性:sbyte,short和int。它还避免抛出溢出异常,并且非常紧凑。它不像上面的for循环那样高性能,但是并不是在所有情况下都需要性能。
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;
}
它适用于无符号整数数据类型,因为C#仅对int和long支持Interlocked.Add()。上述实现也可以轻松修改为支持其他整数和浮点数据类型,以使用CPU的多个内核并行进行求和。在HPCsharp nuget软件包中使用它。
试试这个代码:
using System;
namespace Array
{
class Program
{
static void Main()
{
int[] number = new int[] {5, 5, 6, 7};
int sum = 0;
for (int i = 0; i <number.Length; i++)
{
sum += number[i];
}
Console.WriteLine(sum);
}
}
}
结果是:
23