Convertir un doble en un int en C #

103

En nuestro código tenemos un doble que necesitamos convertir en un int.

double score = 8.6;
int i1 = Convert.ToInt32(score);
int i2 = (int)score;

¿Alguien puede explicarme por qué i1 != i2?

El resultado que obtengo es que: i1 = 9y i2 = 8.

Wouter Dorgelo
fuente
5
Math.Truncate(score)es una intención más explícitamente expresa que(int)score
Lu55
3
Pero Math.Truncate devuelve un doble o decimal, no un int
Sergioet

Respuestas:

164

Porque Convert.ToInt32rondas:

Valor de retorno: redondeado al entero de 32 bits con signo más cercano. Si el valor está a medio camino entre dos números enteros, se devuelve el número par; es decir, 4.5 se convierte en 4 y 5.5 se convierte en 6.

... mientras el elenco se trunca :

Cuando se convierte de un valor doble o flotante a un tipo integral, el valor se trunca.

Actualización: consulte el comentario de Jeppe Stig Nielsen a continuación para ver diferencias adicionales (que, sin embargo, no entran en juego si scorees un número real como es el caso aquí).

Jon
fuente
6
Su enlace realmente lo explica mejor, y no es tan simple como redondear vs truncar: Tipo: Valor System.Int32, redondeado al entero de 32 bits con signo más cercano. Si el valor está a medio camino entre dos números enteros, se devuelve el número par; es decir, 4.5 se convierte en 4 y 5.5 se convierte en 6.
ericosg
@ericosg: Sí, eso enmascararía la diferencia si scorefuera en 8.5lugar de 8.6. Actualicé la respuesta para incluir las citas. Gracias por el aporte.
Jon
5
Y si scorees NaNo un infinito o finito pero fuera del rango de Int32, Convert.ToInt32lanzará una excepción. Cast devolverá un int, pero no sabrás cuál (en mi implementación es Int32.MinValue) porque estás en uncheckedcontexto. (Si está en checkedcontexto, el elenco también lanzará una excepción en estos casos).
Jeppe Stig Nielsen
@JeppeStigNielsen: Gracias por la entrada, actualicé la respuesta para mencionar esto también.
Jon
Agradable. Pero creo que el Doublenúmero de tipo 10000000000.6(diez mil millones punto seis) es un número "real". Usar un yeso inten eso dará un resultado extraño (a menos que esté en checkedcontexto, pero probablemente no lo esté).
Jeppe Stig Nielsen
13

La transmisión ignorará cualquier cosa después del punto decimal, por lo que 8.6 se convierte en 8.

Convert.ToInt32(8.6) es la forma segura de asegurarse de que su doble se redondee al número entero más cercano, en este caso 9.

neilgmacy
fuente
1
Pregunta adicional: ¿qué sucede si el valor del doble es demasiado grande para introducirlo en el int ? Es decir, si es superior a int.MAX_VAL ?
Konrad Viltersten
1
@KonradViltersten Lanza una excepción El valor era demasiado grande o demasiado pequeño para un Int32.
Vamsi
11

puedes redondear tu doble y lanzar ist:

(int)Math.Round(myDouble);
David
fuente
4
la pregunta ahora era cómo hacer i1 == i2. La pregunta era por qué no son iguales. Voto en contra.
Adam
5

En el ejemplo proporcionado, su decimal es 8,6 . Si hubiera sido 8.5 o 9.5, la declaración i1 == i2 podría haber sido cierta. De hecho, habría sido cierto para 8.5 y falso para 9.5.

Explicación:

Independientemente de la parte decimal, la segunda declaración int i2 = (int)scoredescartará la parte decimal y simplemente le devolverá la parte entera. Algo bastante peligroso de hacer, ya que podría producirse una pérdida de datos.

Ahora, para la primera declaración, pueden suceder dos cosas. Si la parte decimal es 5, es decir, está a la mitad, se debe tomar una decisión. ¿Redondeamos hacia arriba o hacia abajo? En C #, la clase Convert implementa el redondeo bancario. Consulte esta respuesta para obtener una explicación más profunda. En pocas palabras, si el número es par, redondee hacia abajo, si el número es impar, redondee hacia arriba.

Por ejemplo, considere:

        double score = 8.5;
        int i1 = Convert.ToInt32(score); // 8
        int i2 = (int)score;             // 8

        score += 1;
        i1 = Convert.ToInt32(score);     // 10
        i2 = (int)score;                 // 9
Evdzhan Mustafa
fuente
2

ToInt32 rondas. La conversión a int simplemente descarta el componente no entero.


fuente