¿Cómo determinar si un decimal / doble es un número entero?

¿Cómo puedo saber si un valor decimal o doble es un número entero?

Por ejemplo:

decimal d = 5.0; // Would be true decimal f = 5.5; // Would be false 

o

 double d = 5.0; // Would be true double f = 5.5; // Would be false 

La razón por la que me gustaría saber esto es para poder determinar mediante progtwigción si quiero generar el valor usando .ToString("N0") o .ToString("N2") . Si no hay un valor de punto decimal, entonces no quiero mostrar eso.

Para números de punto flotante, n % 1 == 0 es típicamente la forma de verificar si hay algo más allá del punto decimal.

  public static void Main (string[] args) { decimal d = 3.1M; Console.WriteLine((d % 1) == 0); d = 3.0M; Console.WriteLine((d % 1) == 0); } 

Salida:

 False True 

Actualización: Como @Adrian Lopez mencionó a continuación, la comparación con un epsilon pequeño valor descartará los cálculos erróneos de computación en coma flotante. Dado que la pregunta es acerca de los valores double , a continuación se mostrará una respuesta de prueba de cálculo con coma flotante :

 Math.Abs(d % 1) <= (Double.Epsilon * 100) 

Hay varias maneras de hacer esto. Por ejemplo:

 double d = 5.0; bool isInt = d == (int)d; 

También puedes usar modulo.

 double d = 5.0; bool isInt = d % 1 == 0; 

¿Qué tal esto?

 public static bool IsInteger(double number) { return number == Math.Truncate(number); } 

Mismo código para decimal

Mark Byers hizo un buen punto, en realidad: esto puede no ser lo que realmente quieres. Si lo que realmente te importa es si un número redondeado a los dos lugares decimales más cercanos es un número entero , puedes hacer esto en su lugar:

 public static bool IsNearlyInteger(double number) { return Math.Round(number, 2) == Math.Round(number); } 

Si bien las soluciones propuestas parecen funcionar para ejemplos simples, hacer esto en general es una mala idea. Es posible que un número no sea exactamente un número entero, pero cuando intenta formatearlo, está lo suficientemente cerca de un número entero que obtiene 1.000000 . Esto puede suceder si se hace un cálculo que en teoría debería dar exactamente 1, pero en la práctica da un número muy cercano pero no exactamente igual a uno debido a errores de redondeo.

En su lugar, formatee primero y si su cadena termina en un período seguido de ceros, quítelos. También hay algunos formatos que puede usar que eliminan ceros finales automáticamente. Esto podría ser lo suficientemente bueno para su propósito.

 double d = 1.0002; Console.WriteLine(d.ToString("0.##")); d = 1.02; Console.WriteLine(d.ToString("0.##")); 

Salida:

 1 1.02 
 bool IsInteger(double num) { if (ceil(num) == num && floor(num) == num) return true; else return false; } 

Problemo solvo.

Editar: Creado por Mark Rushakoff.

Si el límite superior e inferior de Int32 importa:

 public bool IsInt32(double value) { return value >= int.MinValue && value <= int.MaxValue && value == (int)value; } 

La respuesta de Mark Rushakoff puede ser más simple, pero los siguientes también funcionan y pueden ser más eficientes ya que no hay una operación de división implícita:

  bool isInteger = (double)((int)f) == f ; 

y

  bool isInteger = (decimal)((int)d) == d ; 

Si quieres una sola expresión para ambos tipos, quizás

  bool isInteger = (double)((int)val) == (double)val ; 

Puede usar el formato de cadena para el tipo doble. Aquí hay un ejemplo:

 double val = 58.6547; String.Format("{0:0.##}", val); //Output: "58.65" double val = 58.6; String.Format("{0:0.##}", val); //Output: "58.6" double val = 58.0; String.Format("{0:0.##}", val); //Output: "58" 

Avísame si esto no ayuda.

 static bool IsWholeNumber(double x) { return Math.Abs(x % 1) < double.Epsilon; } 

Enfrenté una situación similar, pero donde el valor es una cadena. El usuario escribe un valor que se supone que es un monto en dólares, por lo que quiero validar que sea numérico y que tenga como máximo dos decimales.

Este es mi código para devolver verdadero si la cadena “s” representa un valor numérico con un máximo de dos decimales, y de lo contrario es falso. Evita cualquier problema que resulte de la imprecisión de los valores de coma flotante.

 try { // must be numeric value double d = double.Parse(s); // max of two decimal places if (s.IndexOf(".") >= 0) { if (s.Length > s.IndexOf(".") + 3) return false; } return true; catch { return false; } 

Discuto esto con más detalle en http://progblog10.blogspot.com/2011/04/determining-whether-numeric-value-has.html .

El uso de int.TryParse arrojará estos resultados: var shouldBeInt = 3;

  var shouldntBeInt = 3.1415; var iDontWantThisToBeInt = 3.000f; Console.WriteLine(int.TryParse(shouldBeInt.ToString(), out int parser)); // true Console.WriteLine(int.TryParse(shouldntBeInt.ToString(), out parser)); // false Console.WriteLine(int.TryParse(iDontWantThisToBeInt.ToString(), out parser)); // true, even if I don't want this to be int Console.WriteLine(int.TryParse("3.1415", out parser)); // false Console.WriteLine(int.TryParse("3.0000", out parser)); // false Console.WriteLine(int.TryParse("3", out parser)); // true Console.ReadKey(); 
  public static bool isInteger(decimal n) { return n - (Int64)n == 0; } 

Quizás no sea la solución más elegante, ¡pero funciona si no eres demasiado quisquilloso!

 bool IsInteger(double num) { return !num.ToString("0.################").Contains("."); } 

Podría usar el método ‘TryParse’.

 int.TryParse() 

Esto verifica si el valor se puede convertir a un valor de número entero entero. El resultado puede indicar una bandera que se puede usar en cualquier otro lugar de su código.

Prueba esto:

 number == Convert.ToInt16(number);