¿Cómo convierto un decimal a un int en C #?

227

¿Cómo convierto un decimal a int?

Rob Hruska
fuente
11
Sería útil saber si usted quiere redondear al int más cercano o simplemente dejar los números después del punto decimal (es decir: siempre hacia abajo y vuelta)
Dina
128
Sinceramente, no veo el punto de rechazar preguntas genuinas. sí, la respuesta se puede encontrar en google PERO, ¿no mejoraría la calidad del sitio si la gente dejara de cerrar cada segunda pregunta? no es que esta pregunta es spam o cualquier cosa, y estoy seguro de que sería útil para muchos de nuevos productores a C #
jay_t55

Respuestas:

268

Usar Convert.ToInt32desde mscorlibcomo en

decimal value = 3.14m;
int n = Convert.ToInt32(value);

Ver MSDN . También puedes usar Decimal.ToInt32. Nuevamente, vea MSDN . Finalmente, puedes hacer un elenco directo como en

decimal value = 3.14m;
int n = (int) value;

que usa el operador de conversión explícito. Ver MSDN .

jason
fuente
10
Cuidado: Convertir tiene un comportamiento sorprendente para cierta conversión ( nullvs. 0vs. ""). Recomiendo nunca usar Convertir a menos que necesite absolutamente su flexibilidad (es decir, en escenarios de tipo dinámico)
Eamon Nerbonne
1
-1 ya que esto no funcionará para valores como decimal.MaxValue y decimal.MinValue y da como resultado un OverflowException. Creo que @Will proporciona una mejor respuesta aquí stackoverflow.com/a/501165/39532
mezoid
8
Tenga cuidado, porque Convert.ToInt32y Decimal.ToInt32compórtese de manera diferente. Desde MSDN: Decimal.ToInt32- El valor de retorno es la parte integral del valor decimal; los dígitos fraccionarios se truncan . Convert.ToInt32- Valor de retorno redondeado al entero con signo de 32 bits 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.
vezucci
67

No puedes

Bueno, por supuesto que podría , sin embargo, un int (System.Int32) no es lo suficientemente grande como para contener todos los valores decimales posibles.

Eso significa que si lanza un decimal que es mayor que int.MaxValue, se desbordará, y si el decimal es más pequeño que int.MinValue, se desbordará.

¿Qué sucede cuando estás bajo / desbordado? Una de dos cosas Si su compilación no está marcada (es decir, al CLR no le importa si lo hace), su aplicación continuará después de que el valor exceda / disminuya, pero el valor en el int no será lo que esperaba. Esto puede provocar errores intermitentes y puede ser difícil de solucionar. Terminará su aplicación en un estado desconocido que puede provocar que su aplicación corrompa los datos importantes en los que está trabajando. No está bien.

Si su ensamblaje está marcado (propiedades-> compilación-> avanzado-> verifique el desbordamiento / desbordamiento aritmético o la opción / compilador comprobado), su código arrojará una excepción cuando ocurra un desbordamiento / desbordamiento. Esto es probablemente mejor que no; sin embargo, el valor predeterminado para los ensamblajes no es verificar el exceso / desbordamiento.

La verdadera pregunta es "¿qué estás tratando de hacer?" Sin conocer sus requisitos, nadie puede decirle qué debe hacer en este caso, aparte de lo obvio: NO LO HAGA.

Si específicamente NO te importa, las respuestas aquí son válidas. Sin embargo, debe comunicar su comprensión de que puede ocurrir un desbordamiento y que no importa envolviendo su código de transmisión en un bloque no verificado

unchecked
{
  // do your conversions that may underflow/overflow here
}

De esa manera, las personas que vienen detrás de usted entienden que no le importa, y si en el futuro alguien cambia sus compilaciones a / verificado, su código no se romperá inesperadamente.

Si todo lo que quiere hacer es soltar la parte fraccionaria del número, dejando la parte integral, puede usar Math.Truncate.

decimal actual = 10.5M;
decimal expected = 10M;
Assert.AreEqual(expected, Math.Truncate(actual));

fuente
3
Aunque sospecho que son lo mismo bajo el capó si la entrada es un decimal, me siento más cómodo usando Decimal.Truncate que Math.Truncate, ya que este último también acepta dobles y, por lo tanto, se puede entender que puede truncar números pares que no son de base 10, a diferencia de Decimal.Truncate, que es un verdadero truncamiento de un número de base 10.
Brian
77
Los contextos no verificados no se aplican a los decimales; las operaciones en decimales arrojarán OverflowExceptions independientemente.
Dave
46
int i = (int)d;

le dará el número redondeado hacia abajo.

Si desea redondear al número par más cercano (es decir, se redondeará> .5) puede usar

int i = (int)Math.Round(d, MidpointRounding.ToEven);

En general, puede emitir entre todos los tipos numéricos en C #. Si no hay información que se perderá durante el reparto, puede hacerlo implícitamente:

int i = 10;
decimal d = i;

aunque aún puede hacerlo explícitamente si lo desea:

int i = 10;
decimal d = (decimal)i;

Sin embargo, si va a perder información a través del elenco, debe hacerlo explícitamente (para demostrar que sabe que puede estar perdiendo información):

decimal d = 10.5M;
int i = (int)d;

Aquí estás perdiendo el ".5". Esto puede estar bien, pero debe ser explícito al respecto y hacer un reparto explícito para demostrar que sabe que puede estar perdiendo la información.

ICR
fuente
1
En realidad, desea MidpointRounding.AwayFromZero si desea que> * .5 siempre se redondee según mi experiencia probando el código anterior mirando la salida de muestra aquí: msdn.microsoft.com/en-us/library/…
Elijah Lofgren
@ElijahLofgren Depende un poco: si estás haciendo estadísticas, ToEvendebes evitar la deriva estadística. Sin embargo, si opera con artículos o dinero con cargo, AwayFromZeroparece ser la opción correcta.
mbx
22
decimal d = 2;
int i = (int) d;

Esto debería funcionar bien.

luiscubal
fuente
Cuidado, con una conversión explícita la información podría perderse.
Fedro
21
Al convertir de decimal a int, la información casi siempre se perderá, pero creo que ese es el punto.
Dinah
8

System.Decimalimplementa la IConvertableinterfaz, que tiene un ToInt32()miembro.

¿Las llamadas System.Decimal.ToInt32()funcionan para ti?

Andy
fuente
2
De la documentación : "Esta API es compatible con la infraestructura de .NET Framework y no está diseñada para usarse directamente desde su código". ¿Por qué no usar Convert.ToInt32?
H.Wolper
7

Un buen truco para el redondeo rápido es agregar .5 antes de convertir su decimal a int.

decimal d = 10.1m;
d += .5m;
int i = (int)d;

Todavía se va i=10, pero

decimal d = 10.5m;
d += .5m;
int i = (int)d;

Redondearía para que i=11.

DeadlyBrad42
fuente
55
¿Por qué molestarse en hacer esto cuando hay Math.Floor y Math.Ceiling?
Badaro
En ese momento, era bastante nuevo en C # y por alguna razón no me di cuenta de que estas funciones existían. En realidad, es un truco que aprendí de C / C ++, donde obviamente fue más útil.
DeadlyBrad42
1
¿Qué pasa si el valor decimal era, por ejemplo, -9.3?
supercat
6

Prefiero usar Math.Round , Math.Floor , Math.Ceiling o Math.Truncate para establecer explícitamente el modo de redondeo según corresponda.

Tenga en cuenta que todos ellos también devuelven Decimal, ya que Decimal tiene un rango de valores mayor que un Int32, por lo que aún tendrá que emitir (y verificar si hay desbordamiento / desbordamiento).

 checked {
   int i = (int)Math.Floor(d);
 }
Mark Brackett
fuente
6

Redondeando un decimal al entero más cercano

decimal a ;
int b = (int)(a + 0.5m);

cuando a = 49.9entoncesb = 50

cuando a = 49.5entoncesb = 50

cuando a = 49.4, entonces b = 49etc.

sonámbulo
fuente
0

Me parece que el operador de conversión no funciona si tiene un decimal en caja (es decir, un valor decimal dentro de un tipo de objeto). Convert.ToInt32 (decimal como objeto) funciona bien en este caso.

Esta situación surge cuando se recuperan los valores IDENTITY / AUTONUMBER de la base de datos:

SqlCommand foo = new SqlCommand("INSERT INTO...; SELECT SCOPE_IDENTITY()", conn);
int ID = Convert.ToInt32(foo.ExecuteScalar());  // works
int ID = (int)foo.ExecuteScalar();              // throws InvalidCastException

Ver 4.3.2 Conversiones de Unboxing

Timbo
fuente
2
Agregarle más como referencia: eso se debe a que solo puede desempaquetar al mismo tipo original. Aquí SELECT SCOPE_IDENTITY()vuelve lo numeric(38, 0)que se traduce en decimal.NET. foo.ExecuteScalar()devuelve un decimalcuadro en el objectque no se puede lanzar directamente a un int. (int)(decimal)foo.ExecuteScalar()o Convert.ToInt32(foo.ExecuteScalar())funcionaría
rageit
0

Ninguna respuesta parece tratar con la excepción OverflowException / UnderflowException que proviene de intentar convertir un decimal que está fuera del rango de int.

int intValue = (int)Math.Max(int.MinValue, Math.Min(int.MaxValue, decimalValue));

Esta solución devolverá el valor int máximo o mínimo posible si el valor decimal está fuera del rango int. Es posible que desee agregar algunos redondeos con Math.Round, Math.Ceiling o Math.Floor para cuando el valor esté dentro del rango int.

Kapten-N
fuente