web-dev-qa-db-fra.com

Comment résumer un tableau d'entiers en C #

Y a t-il meilleur moyen plus court que de parcourir le tableau?

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

clarification:

Un meilleur primaire signifie un code plus propre, mais des suggestions d'amélioration des performances sont également les bienvenues. (Comme déjà mentionné: division de grands tableaux).


Ce n'est pas comme si je cherchais à améliorer vos performances - je me demandais si ce type de sucre syntaxique n'était pas déjà disponible: "Il y a String.Join - qu'est-ce qui se passe avec int []?".

84
Filburt

Si vous pouvez utiliser C # 3.5 et LINQ, essayez 

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

Oui il y a. Avec .NET 3.5:

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

Si vous n'utilisez pas .NET 3.5, vous pouvez procéder comme suit:

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

Avec LINQ:

arr.Sum()
18
Chris

Cela dépend de la façon dont vous définissez mieux. Si vous voulez que le code paraisse plus propre, vous pouvez utiliser .Sum () comme indiqué dans d'autres réponses. Si vous souhaitez que l'opération s'exécute rapidement et que vous disposiez d'un grand tableau, vous pouvez le rendre parallèle en le décomposant en sous-sommes, puis en faisant la somme des résultats.

5
unholysampler

Si vous ne préférez pas LINQ, il est préférable d'utiliser la boucle foreach pour éviter les erreurs d'index.

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

Pour les baies extrêmement volumineuses, il peut être avantageux d’effectuer le calcul en utilisant plusieurs processeurs/cœurs de la 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);
});
2
Theodor Zoulias

Un problème avec les solutions de boucle for ci-dessus est que pour le tableau d'entrée suivant avec toutes les valeurs positives, le résultat de la somme est négatif:

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

La somme est -2147483648, car le résultat positif est trop grand pour le type de données int et déborde dans une valeur négative.

Pour le même tableau d’entrée, les suggestions arr.Sum () provoquent la génération d’une exception de débordement.

Une solution plus robuste consiste à utiliser un type de données plus volumineux, tel qu'un "long" ou un "double" dans ce cas, pour la "somme" comme suit:

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

Pour les versions beaucoup plus rapides qui implémentent le parallèle de données (SIMD/SSE) et le multi-core, vous pouvez utiliser le package nuget HPCsharp ( https://www.nuget.org/packages/HPCsharp/ ), qui est open source et libre. Ces implémentations sont bien plus rapides que les arrêts Linq arr.Sum () et arr.AsParallel.Sum () et ne génèrent pas d'exception de débordement ni de débordement dans les négatifs.

HPCsharp implémente également un arr.Sum () plus précis pour les tableaux flottants et doubles, en utilisant les algorithmes de sommation à virgule flottante de Kahan et Neumaier.

1
DragonSpit

L'utilisation de foreach serait un code plus court, mais vous ferez probablement exactement les mêmes étapes au moment de l'exécution, une fois que l'optimisation JIT reconnaît la comparaison à Length dans l'expression de contrôle for-loop.

0
Ben Voigt

Dans l'une de mes applications, j'ai utilisé:

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

Une alternative consiste également à utiliser la méthode d'extension Aggregate().

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