2010-11-02 21 views
18

Possible Duplicate:
How to determine if a decimal/double is an integer?¿Cuál es una buena manera de verificar si un doble es un número entero en C#?

Tengo una variable de tipo double y quiero comprobar si es un número entero.

Por el momento tengo

public bool CheckIfInteger(double number) 
{ 
    return number.ToString().Contains(".") == false; 
} 

¿hay una manera mejor?

ACTUALIZACIÓN: Lo siento, no me di cuenta de la posibilidad de confusión, por entero me refería a la definición matemática del número entero, es decir, los números naturales junto con los negativos de los números naturales distintos de cero.

+8

Su camino es arriesgado: ¿y si la configuración regional de la máquina tiene "," como separador decimal? Parece que puede elegir entre las respuestas a continuación. :) –

+0

Lo primero que se le viene a la mente con el enfoque actual que utiliza es que podría no tener en cuenta que el separador decimal podría ser diferente según la cultura del hilo actual. Si va a elegir una de las alternativas de las respuestas a continuación, tenga cuidado con cualquier cosa que trate el número de entrada como una cadena antes de darle un resultado ... especialmente si no cuenta para los separadores decimales que no sean "." –

+0

@Shadow: su caso puede ser provisional con 'CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator'. Pero ¿qué pasa con '((decimal)) Int32.MaxValue + 1)'? Es un decimal sin separador decimal – abatishchev

Respuesta

29
return Math.Truncate(number) == number; 

Como se mencionó en los comentarios, puede que tenga que tener en cuenta el hecho de que una representación double de su número podría no ser un número entero exacto. En ese caso, tendrá que permitir un cierto margen de error de-:

double diff = Math.Abs(Math.Truncate(number) - number); 
return (diff < 0.0000001) || (diff > 0.9999999); 
+7

Sin embargo, tenga en cuenta los problemas de precisión de coma flotante: con 'double number = 100.0 * (8183.23 - 6695.37)' obtendría 'false' con este método. –

6

Probar:

public bool CheckIfInteger(double number) 
{ 
    return ((double) (int) number == number); 
} 

O el más bonito:

public bool CheckIfInteger(double number) 
{ 
    return (Math.Floor(number) == number); 
} 
+0

¿Por qué vuelves a int para duplicar nuevamente? – nawfal

24

Si desea comprobar si hay un entero, esto hará que:

public bool IsInteger(double number) 
{ 
    return (number % 1 == 0); 
} 

Si quieres, además, a compruebe si el número se puede convertir en un Int32:

public bool IsInt32(double number) 
{ 
    return (number % 1 == 0) && number >= Int32.MinValue && number <= Int32.MaxValue; 
} 
+3

esto no funcionará en casos de valores dobles grandes, el rango de valores de doble es mayor que el de int. TryParse te dará falso debido al rango, pero tu mod será verdadero. Pruébelo con double.MaxValue – BrokenGlass

+0

Gracias por la nota, actualicé mi respuesta. –

+0

@BrokenGlass, @Tim: la pregunta dice "entero", no "int" o "Int32". La lógica original de Tim era correcta, ya que coincidía con lo que el OP intenta en la pregunta, volviendo verdadero para cualquier entero 'doble', de lo contrario es falso. (Idealmente, el OP debería aclarar si quieren decir 'Int32' o simplemente entero.) – LukeH

4

que haría uso de TryParse:

double value = 2.0; 
    int number; 
    bool result = Int32.TryParse(value.ToString(), out number); 
0

utilizo el siguiente método de extensión de cadena que comprueba contra un patrón de expresión

public static bool IsInteger(this string inputString) 
    { 
     Regex regexInteger = new Regex(@"^[-]?\d+$"); 
     Match m = regexInteger.Match(inputString); 
     return m.Success; 
    } 
+5

esto no funcionará en muchos casos, incluido el desbordamiento, el rango de valores de doble es mayor que el de int. Ahora tienes dos problemas. – BrokenGlass

+0

Comentario equitativo - acordado – Madeleine

+1

¿Esto también fallará cuando un número negativo no se expresa como -1, sino como (1)? –

15

El peligro de trabajar con representaciones de cadenas es la configuración regional utilizada y debe ocuparse de los problemas de redondeo. 0.999999999 se puede considerar que es el número entero 1 en la mayoría de los casos. Aquí es un pequeño fragmento teniendo en cuenta los errores de redondeo:

Math.Abs(number - Math.Round(number)) < EPSILON 

donde EPSILON es un doble valor que es lo suficientemente pequeño para su propósito 0,00001 por ejemplo

Véase también esto para algo más de información: http://msdn.microsoft.com/en-us/library/system.double.epsilon.aspx

+5

+1 por mencionar épsilon. – Polyfun

2
public static bool CheckIfInteger(double number) 
    { 
     return number - Math.Truncate(number) == 0; 
    } 
+2

¿Qué tal el número == Math.Truncate (number)? – JohannesH

2

Creo que una mejor pregunta es: ¿Cómo puedo saber si un doble está lo suficientemente cerca de un número entero como para ser considerado como un número entero para mis propósitos? Porque de lo contrario, es probable que se encuentre con ambigüedades. Así que recomiendo algo como esto:

return Math.Abs(someDouble - Math.Round(someDouble)) < TOLERANCE; 
1

me está gustando la idea de utilizar abatishchev CurrentCulture.

return number.ToString().Contains(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator) == false; 

¿Esto no resolvería el problema épsilon (que ni siquiera consideré inicialmente)?

Cuestiones relacionadas