2010-01-23 6 views
24

Tengo dos enteros que quiero dividir para obtener un porcentaje.¿Cuál es la mejor manera de crear un valor porcentual a partir de dos enteros en C#?

Esto es lo que tengo en este momento:

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

Esto da la respuesta correcta. Pero eso es mucho casting para hacer algo tan simple como obtener un porcentaje entre dos números.

¿Hay una mejor manera de hacerlo? ¿Algo que no involucre el casting?

+0

¡Gracias por las excelentes respuestas! ¡Vota por todos lados! – Vaccano

Respuesta

42

¿Qué tal solo mappedItems * 100.0/totalItems y lo fundimos en el tipo apropiado?

+9

Tenga cuidado con la división por 0 si la lista está vacía. –

+2

o agregue un sufijo 'M' como' * 100M'. –

+0

La solución original permite valores de elementos asignados dentro del rango completo (Int32.MaxValue/Int32.MinValue). Su solución causará un desbordamiento de valores> (Int32.MaxValue/100) o <(Int32.MinValue/100) –

1

Puede usar (mappedItems * 100)/totalItems pero esto siempre redondeará hacia abajo. El método que has usado es mejor. ¿Por qué no envolver el código como un método?

+0

La sugerencia de John es mejor. – Mick

4

Bueno, suponiendo que el recuento es menor que int.MaxValue:

int percent = mappedItems * 100/totalItems; 
7

Si sólo quería evitar los moldes, se podría escribir:

(100 * mappedItems)/totalItems 

pero que se desbordará rápidamente cuando mappedItems > int.MaxValue/100 .

Y ambos métodos redondean el porcentaje hacia abajo. Para obtener el redondeo correcto, me gustaría mantener el resultado como un doble:

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

Usted puede obtener un resultado correctamente redondeada utilizando sólo operaciones con enteros:

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

Por multiplyingby dos, la adición de uno y dividiendo por dos , efectivamente está agregando una mitad. Esto hace que la división entera haga un redondeo en lugar de truncar.

+2

Su fórmula no es correcta y no funciona. Vea mi respuesta para la fórmula correcta y explicaciones. – dragonroot

1

Sólo para añadir que a medida que tienes int s y desea calcular el porcentaje (un valor de punto flotante) que se va a tiene que hacer la colada. Ya sea explícito como en C# o implícito como en algunos lenguajes de scripting, el lanzamiento seguirá ocurriendo. Es mejor hacerlo explícito.

Si quieren un menor número de moldes por línea de código que podría escribir:

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

Aunque como otros han señalado - comprobar si hay totalItems siendo 0 (preferiblemente antes de emitir duplicar) para evitar una división por cero.

1

probar esto:

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

en este ejemplo, se obtendría como resultado de ser "50"

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

La forma número entero de sólo adecuado para obtener el porcentaje de redondeo adecuado es:

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

¿Cómo llegar?Si hacemos esto en coma flotante, sería Math.Floor(mappedItems * 100.0/totalItems + 0.5). Necesitamos transformar esta fórmula para que sea solo un número entero multiplicando y dividiendo 0.5 por totalItems, luego moviendo 0.5 * totalItems en dividendo, y luego multiplicando dividendo y divisor por 2 para hacer que las fracciones desaparezcan:

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

En este momento, la fórmula es solo de números enteros. Cuando hacemos la división de enteros, obtenemos el resultado de piso, por lo que el resultado de entero solo es equivalente al punto flotante mencionado.

Cuestiones relacionadas