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?



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.


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


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.


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;
}

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


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();

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.



3

Aquí hay una buena solución:

if (variable == (int)variable) {
    //logic
}

¿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()

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);
}

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.


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.


0

Mi solución simple:

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

-1

Aquí hay una solución:

float var = Your_Value;
if ((var - Math.floor(var)) == 0.0f)
{
    // var is an integer, so do stuff
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.