2010-01-23 17 views
24

Ho due interi che voglio dividere per ottenere una percentuale.Qual è il modo migliore per creare un valore percentuale da due numeri interi in C#?

Questo è ciò che ho in questo momento:

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

Questo dà la risposta giusta. Ma questo è un sacco di casting per fare qualcosa di semplice come ottenere una percentuale tra due numeri.

C'è un modo migliore per farlo? Qualcosa che non implichi il casting?

+0

Grazie per le grandi risposte! Voti in tutto! – Vaccano

risposta

42

Che ne dici di solo mappedItems * 100.0/totalItems e trasmettere questo al tipo appropriato?

+9

Fai attenzione con la divisione di 0 se la lista è vuota. –

+2

o aggiungi un suffisso 'M' come' * 100M'. –

+0

La soluzione originale consente i valori di oggetti mapped nell'intero intervallo (Int32.MaxValue/Int32.MinValue). La soluzione causerà un overflow per valori> (Int32.MaxValue/100) o <(Int32.MinValue/100) –

1

È possibile utilizzare (mappedItems * 100)/totalItems, ma questo è sempre arrotondato per difetto. Il metodo che hai usato è migliore. Perché non avvolgere il codice come metodo?

+0

Il suggerimento di Giovanni è migliore. – Mick

4

Beh, supponendo che la conta sono più piccoli di int.MaxValue:

int percent = mappedItems * 100/totalItems; 
7

Se si voleva solo per evitare i calchi, si potrebbe scrivere:

(100 * mappedItems)/totalItems 

ma che rapidamente traboccare quando mappedItems > int.MaxValue/100 .

E entrambi i metodi arrotondano la percentuale verso il basso. Per ottenere corretto arrotondamento, voglio mantenere il risultato come un doppio:

((double)mappedItems /(double) totalItems) * 100 
6

si può ottenere un risultato correttamente arrotondato usando solo operazioni intere:

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

Per multiplyingby due, aggiungendo uno e dividendo per due , stai effettivamente aggiungendo una metà. Questo rende la divisione intera un arrotondamento invece di troncare.

+2

La tua formula non è giusta e non funziona. Vedi la mia risposta per la formula e le spiegazioni giuste. – dragonroot

1

solo aggiungere che, come hai int s e si vuole calcolare la percentuale (un valore in virgola mobile) che si sta per avere fare casting. Che sia esplicito come in C# o implicito come in alcuni linguaggi di scripting, il cast continuerà comunque. È meglio renderlo esplicito.

Se si desidera un minor numero di calchi per riga di codice si potrebbe scrivere:

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

Anche se, come altri hanno fatto notare - verificare la presenza di totalItems essere 0 (preferibilmente prima del getto di raddoppiare) per evitare una divisione per zero.

1

provare questo:

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

in questo esempio, si potrebbe risultare essere "50"

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

Il modo intero solo giusto per ottenere la percentuale con una corretta arrotondamento ottiene è:

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

Come ci si arriva?Se facciamo questa cosa in virgola mobile, sarebbe Math.Floor(mappedItems * 100.0/totalItems + 0.5). Dobbiamo trasformare questa formula in numero intero, moltiplicando e dividendo 0.5 per totalItems, quindi spostando 0.5 * totalItems in dividendo e moltiplicando dividendo e divisore per 2 per far scomparire le frazioni:

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).

A questo punto la formula è solo per numeri interi. Quando eseguiamo la divisione intero, otteniamo un risultato floored, quindi il risultato solo-intero è equivalente a quello a virgola mobile citato.

Problemi correlati