Cómo probar si un doble es un número entero

165

¿Es posible hacer esto?

double variable;
variable = 5;
/* the below should return true, since 5 is an int. 
if variable were to equal 5.7, then it would return false. */
if(variable == int) {
    //do stuff
}

Sé el código probablemente no va nada por el estilo, pero ¿cómo lo hace que se vaya?

JXPheonix
fuente
1
C # pero similar en Java: stackoverflow.com/a/4077262/284240 ( Integer.MAX_VALUE )
Tim Schmelter
1
¿Qué ganarías con esto? doubley intestán representados en la memoria de manera diferente, y usaría uno u otro según el contexto de su manejo de memoria.
Makoto
@Leyenda, hubiera hecho lo mismo que sugirió; ¿sabe por casualidad cómo% 1 se compara en términos de eficiencia con Math.floor (variable) que sugirieron otros usuarios?
G. Bach
3
@ Makoto Es un programa para encontrar triples de pygatorean. Las raíces cuadradas a veces pueden ser dobles, pero al mismo tiempo también pueden ser números enteros. ¿Entiendes lo que quiero decir?
JXPheonix
@JXPheonix: por lo tanto, los valores pueden ser un valor de punto flotante o un valor entero. Tiene sentido.
Makoto

Respuestas:

146
if ((variable == Math.floor(variable)) && !Double.isInfinite(variable)) {
    // integer type
}

Esto verifica si el valor redondeado hacia abajo del doble es el mismo que el doble.

Su variable podría tener un valor int o doble y Math.floor(variable)siempre tiene un valor int, por lo que si su variable es igual a, Math.floor(variable)entonces debe tener un valor int.

Esto tampoco funciona si el valor de la variable es infinito o infinito negativo, por lo tanto, agrega 'mientras la variable no sea infinita' a la condición.

maxhud
fuente
3
"Si el argumento es NaN o un infinito o cero positivo o cero negativo, entonces el resultado es el mismo que el argumento". docs.oracle.com/javase/6/docs/api/java/lang/…
Tim Schmelter
2
@TimSchmelter: buena captura. También vale la pena señalar que NaN no es igual a nada (incluido él mismo) pero +/- Inf es igual a sí mismo, ¡así que hay dos casos extremos!
Maerics
Tanto Skon como Fouad publicaron respuestas mucho mejores.
Joel Christophel
@JoelChristophel: no estoy de acuerdo. Esta es una buena manera, ya que elimina el riesgo de desbordamiento de tipo. Lo único que no me gustó fue la afirmación de que la variable era un intsi la ifevaluaba true.
Betsabé
@Bathsheba (Double.POSITIVE_INFINITY% 1) == 0 y su contraparte negativa se evalúan como falsas.
Joel Christophel
222

O podría usar el operador de módulo:

(d % 1) == 0

SkonJeet
fuente
2
Realmente amo la simplicidad de esta solución. Es fácil de leer e implementar.
krispy
1
Solución muy intuitiva
Daniel San
3
En términos de cálculo, ¿es más rápido que Math.rint(d)?
iTurki
2
Sí, esto es bueno, pero tenga en cuenta que esta es una solución de Java y no está bien definida para negativo den C y C ++.
Betsabé
44
En Sonar, esto produce un problema: "Las pruebas de igualdad no deben realizarse con valores de coma flotante".
Julio D
86

Guayaba: DoubleMath.isMathematicalInteger. (Divulgación: lo escribí). O, si aún no está importando guayaba, x == Math.rint(x)es la forma más rápida de hacerlo; rintes mediblemente más rápido que flooro ceil.

Louis Wasserman
fuente
3
No sabía sobre Math.rint Estás en lo correcto. Es mucho más rápido que Math.floor
Lenny Markus el
¿Es esto de alguna manera preferible al ejemplo de casting del Ing. Fortouad?
Joel Christophel
@JoelChristophel: Sí. No todos los dobles con valores enteros están en el rango de int, o incluso largos, por lo que la prueba no funcionará en ellos.
Louis Wasserman
Gotcha Entonces (d% 1) == 0 sigue siendo válido.
Joel Christophel
20
public static boolean isInt(double d)
{
    return d == (int) d;
}
Eng.Fouad
fuente
6

Intenta de esta manera,

public static boolean isInteger(double number){
    return Math.ceil(number) == Math.floor(number); 
}

por ejemplo:

Math.ceil(12.9) = 13; Math.floor(12.9) = 12;

por lo tanto, 12.9 no es entero, sin embargo

 Math.ceil(12.0) = 12; Math.floor(12.0) =12; 

por lo tanto 12.0 es entero

Sheldon
fuente
3

Aquí hay una versión para Integery Double:

    private static boolean isInteger(Double variable) {
    if (    variable.equals(Math.floor(variable)) && 
            !Double.isInfinite(variable)          &&
            !Double.isNaN(variable)               &&
            variable <= Integer.MAX_VALUE         &&
            variable >= Integer.MIN_VALUE) {
        return true;
    } else {
        return false;
    }
}

Para convertir Doublea Integer:

Integer intVariable = variable.intValue();
irudyak
fuente
3

Considerar:

Double.isFinite (value) && Double.compare (value, StrictMath.rint (value)) == 0

Esto se adhiere al núcleo de Java y evita una comparación de igualdad entre valores de punto flotante ( ==) que se considera incorrecto. El isFinite()es necesario, ya rint()que pasará a través de los valores del infinito.

simon.watts
fuente
3

La mejor manera es con el operador de módulo

if(val % 1 == 0)
Abdul Hafeez Khan
fuente
1
¿Puedes agregar más explicaciones para responder? ¡Gracias!
Shanteshwar Inde
3

Aquí hay una buena solución:

if (variable == (int)variable) {
    //logic
}
Nitish
fuente
¿Por qué el (bool)elenco?
xdavidliu
1
@xdavidliu No hay necesidad de eso. Podemos ignorarlo.
Nitish
2

Similar a la respuesta de SkonJeet anterior, pero el rendimiento es mejor (al menos en Java):

Double zero = 0d;    
zero.longValue() == zero.doubleValue()
edwardsayer
fuente
1
public static boolean isInteger(double d) {
  // Note that Double.NaN is not equal to anything, even itself.
  return (d == Math.floor(d)) && !Double.isInfinite(d);
}
maerics
fuente
Una implementación más correcta devolvería falso y tendría que escribir otro método que tome int como argumento y devuelva verdadero. : D
alfa
0

podría intentar de esta manera: obtenga el valor entero del doble, reste esto del valor doble original, defina un rango de redondeo y pruebe si el número absoluto del nuevo valor doble (sin la parte entera) es mayor o menor que su Rango definido. si es más pequeño, puede pensar que es un valor entero. Ejemplo:

public final double testRange = 0.2;

public static boolean doubleIsInteger(double d){
    int i = (int)d;
    double abs = Math.abs(d-i);
    return abs <= testRange;
}

Si asigna a d el valor 33.15, el método devuelve verdadero. Para obtener mejores resultados, puede asignar valores más bajos a testRange (como 0.0002) a su discreción.

Salvi94
fuente
0

Personalmente, prefiero la solución de operación de módulo simple en la respuesta aceptada. Desafortunadamente, a SonarQube no le gustan las pruebas de igualdad con puntos flotantes sin establecer una precisión de redondeo. Por eso, hemos tratado de encontrar una solución más compatible. Aquí está:

if (new BigDecimal(decimalValue).remainder(new BigDecimal(1)).equals(BigDecimal.ZERO)) {
    // no decimal places
} else {
    // decimal places
}

Remainder(BigDecimal)devuelve un BigDecimalcuyo valor es (this % divisor). Si este es igual a cero, sabemos que no hay punto flotante.

chaeschuechli
fuente
0

Mi solución simple:

private boolean checkIfInt(double 
 value){
 return value - Math.floor(value) == 0;
 }
Mostafa Amer
fuente
-1

Aquí hay una solución:

float var = Your_Value;
if ((var - Math.floor(var)) == 0.0f)
{
    // var is an integer, so do stuff
}
MOHIT GUPTA
fuente