web-dev-qa-db-fra.com

Quelle est la meilleure façon de créer un pourcentage à partir de deux entiers en C #?

J'ai deux entiers que je veux diviser pour obtenir un pourcentage.

Voici ce que j'ai en ce moment:

int mappedItems = someList.Count(x => x.Value != null);
int totalItems = someList.Count();
(int)(((double)mappedItems /(double) totalItems) * 100)

Cela donne la bonne réponse. Mais c'est beaucoup de casting pour faire quelque chose d'aussi simple que d'obtenir un pourcentage entre deux nombres.

Y a-t-il une meilleure manière de faire cela? Quelque chose qui n'implique pas de casting?

29
Vaccano

Que diriez-vous juste de mappedItems * 100.0 / totalItems et en le moulant au type approprié?

46
John Feminella

Si vous vouliez juste éviter les lancers, vous pourriez écrire:

(100 * mappedItems) / totalItems

mais cela débordera rapidement lorsque mappedItems > int.MaxValue / 100.

Et les deux méthodes arrondissent le pourcentage. Pour obtenir un arrondi correct, je conserverais le résultat sous forme de double:

((double)mappedItems /(double) totalItems) * 100
8
oefe

Le bon moyen d'entier uniquement pour obtenir un pourcentage avec un arrondi correct est:

int result = ( mappedItems * 200 + totalItems ) / ( totalItems * 2 );

Comment pouvons-nous y arriver? Si nous faisons cette chose en virgule flottante, ce serait Math.Floor( mappedItems * 100.0 / totalItems + 0.5 ). Nous devons transformer cette formule en entier uniquement en multipliant et en divisant 0,5 par totalItems, puis en déplaçant 0,5 * totalItems en dividende, puis en multipliant le dividende et le diviseur par 2 pour faire disparaître les fractions:

mappedItems * 100.0/totalItems + 0.5 => mappedItems * 100.0/totalItems + totalItems * 0.5/totalItems => (mappedItems * 100.0 + 0.5 * totalItems)/totalItems => (mappedItems * 200.0 + totalItems)/(totalItems * 2).

À ce stade, la formule est uniquement un entier. Lorsque nous effectuons une division entière, nous obtenons un résultat plancher, donc le résultat entier uniquement est équivalent à celui en virgule flottante mentionné.

8
dragonroot

Vous pouvez obtenir un résultat correctement arrondi en utilisant uniquement des opérations entières:

int percent = (200 * mappedItems + 1) / (totalItems * 2);

En multipliant par deux, en ajoutant un et en divisant par deux, vous ajoutez effectivement une moitié. Cela fait que la division entière fait un arrondi au lieu de la tronquer.

6
Guffa

Eh bien, en supposant que vos comptes sont inférieurs à int.MaxValue:

int percent = mappedItems * 100 / totalItems;
4
tster

Vous pouvez utiliser (mappedItems * 100)/totalItems mais cela s'arrondit toujours. La méthode que vous avez utilisée est meilleure. Pourquoi ne pas envelopper le code comme méthode?

1
Mick

Juste pour ajouter que vous avez ints et que vous voulez calculer le pourcentage (une valeur à virgule flottante) que vous allez avoir pour faire le casting. Que ce soit explicite comme en C # ou implicite comme dans certains langages de script, la conversion se produira toujours. Il vaut mieux le rendre explicite.

Si vous voulez moins de transtypages par ligne de code, vous pouvez écrire:

double mappedItems = (double)someList.Count(x => x.Value != null);
double totalItems = (double)someList.Count();
double percentage = (mappedItems / totalItems) * 100.0);

Bien que comme d'autres l'ont souligné - vérifiez que totalItems est 0 (de préférence avant de transtyper en double) pour éviter une division par zéro.

1
ChrisF

essaye ça:

int mappedItems = someList.Count(x => x.Value != null);
int totalItems = someList.Count();
int percent = Convert.ToInt32(complete * 100.0 / total);

dans cet exemple, le résultat serait "50"

int mappedItems = 14;
int totalItems = 28;
int result = Convert.ToInt32(mappedItems * 100.0 / totalItems);
// result is 50
1
Brad Parks