Como testar se um duplo é um número inteiro

165

É possível fazer isso?

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
}

Eu sei o código provavelmente não vai qualquer coisa assim, mas como é que ele vai?

JXPheonix
fonte
1
C #, mas semelhante em Java: stackoverflow.com/a/4077262/284240 ( Integer.MAX_VALUE )
Tim Schmelter
1
O que você ganha com isso? doublee intsão representados na memória de maneira diferente e você usaria um ou outro com base no contexto de seu tratamento de memória.
27712 Makoto
@ Legend, eu teria feito o mesmo que você sugeriu; por acaso, você sabe como o% 1 compara a eficiência com o Math.floor (variável) sugerido por outros usuários?
G. Bach
3
@ Makoto É um programa para encontrar triplos pigmeus. As raízes quadradas às vezes podem ser duplas, mas, ao mesmo tempo, também podem ser intergers. Entendeu o que eu quis dizer?
JXPheonix
@JXPheonix: Portanto, os valores podem ser um valor de ponto flutuante ou um valor inteiro. Faz sentido.
27412 Makoto

Respostas:

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

Isso verifica se o valor arredondado do dobro é o mesmo que o dobro.

Sua variável pode ter um valor int ou duplo e Math.floor(variable)sempre possui um valor int; portanto, se sua variável for igual a Math.floor(variable), ela deverá ter um valor int.

Isso também não funciona se o valor da variável for infinito ou infinito negativo, portanto, adicionando 'enquanto a variável não for inifinita' à condição.

maxhud
fonte
3
"Se o argumento for NaN ou um infinito ou zero positivo ou zero negativo, o resultado será o mesmo que o argumento". docs.oracle.com/javase/6/docs/api/java/lang/…
Tim Schmelter
2
@ TimSchmelter: boa captura. Também vale a pena notar que NaN não é igual a nada (incluindo ele próprio), mas +/- Inf é igual a si mesmo - portanto, existem dois casos extremos!
27512 maerics
Skon e Fouad publicaram respostas muito melhores.
Joel Christophel
@JoelChristophel: Eu não concordo. Essa é uma boa maneira, pois elimina o risco de excesso de tipo. A única coisa que eu não gostei foi a afirmação de que a variável era intse a ifavaliação é positiva true.
Bathsheba
@Bathsheba (Double.POSITIVE_INFINITY% 1) == 0 e sua contraparte negativa são avaliadas como falsas.
Joel Christophel
222

Ou você pode usar o operador módulo:

(d % 1) == 0

SkonJeet
fonte
2
Eu realmente amo a simplicidade desta solução. É fácil de ler e implementar.
krispy
1
Solução muito intuitiva
Daniel San
3
Em termos de computação, é mais rápido que Math.rint(d)?
iTurki
2
Sim, isso é legal, mas observe que esta é uma solução Java e não está bem definida para negativos dem C e C ++.
Bathsheba
4
No Sonar, isso produz um problema "Os testes de igualdade não devem ser feitos com valores de ponto flutuante".
Julio D
86

Goiaba: DoubleMath.isMathematicalInteger. (Divulgação: escrevi.) Ou, se você ainda não está importando o Guava, x == Math.rint(x)é a maneira mais rápida de fazê-lo; rinté mensurável mais rápido que floorou ceil.

Louis Wasserman
fonte
3
Não sabia sobre Math.rint Você está correto. É a maneira mais rápida do que Math.floor
Lenny Markus
Isso é de alguma forma preferível ao exemplo de elenco do Eng.Fouad?
Joel Christophel
@JoelChristophel: Sim. Nem todas as duplas com valores inteiros estão no intervalo de int, ou mesmo longo, para que o teste não funcione neles.
Louis Wasserman
Peguei vocês. Então (d% 1) == 0 ainda é válido.
Joel Christophel
20
public static boolean isInt(double d)
{
    return d == (int) d;
}
Eng.Fouad
fonte
6

Tente assim,

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

por exemplo:

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

portanto 12.9 não é inteiro, no entanto

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

portanto 12.0 é um número inteiro

Sheldon
fonte
3

Aqui está uma versão para Integere 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 converter Doublepara Integer:

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

Considerar:

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

Isso adere ao Java principal e evita uma comparação de igualdade entre valores de ponto flutuante ( ==) que são considerados ruins. O isFinite()é necessário, pois rint()passará através dos valores infinitos.

simon.watts
fonte
3

A melhor maneira é com o operador de módulo

if(val % 1 == 0)
Abdul Hafeez Khan
fonte
1
você pode adicionar mais explicações para responder? Obrigado!
Shanteshwar Inde
3

Aqui está uma boa solução:

if (variable == (int)variable) {
    //logic
}
Nitish
fonte
por que o (bool)elenco?
xdavidliu 11/01
1
@xdavidliu Não há necessidade disso. Nós podemos ignorá-lo.
Nitish 17/01
2

Semelhante à resposta do SkonJeet acima, mas o desempenho é melhor (pelo menos em java):

Double zero = 0d;    
zero.longValue() == zero.doubleValue()
edwardsayer
fonte
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
fonte
Uma implementação mais correta retornaria false e você teria que escrever outro método que aceite int como argumento e retorne true. : D
alfa
0

você pode tentar desta maneira: obter o valor inteiro do dobro, subtrair do valor duplo original, definir um intervalo de arredondamento e testar se o número absoluto do novo valor duplo (sem a parte inteira) for maior ou menor que o seu intervalo definido. se for menor, você pode pretender que seja um valor inteiro. Exemplo:

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

Se você atribuir a d o valor 33.15, o método retornará true. Para obter melhores resultados, você pode atribuir valores mais baixos a testRange (como 0,0002) a seu critério.

Salvi94
fonte
0

Pessoalmente, prefiro a solução simples de operação do módulo na resposta aceita. Infelizmente, o SonarQube não gosta de testes de igualdade com pontos flutuantes sem definir uma precisão redonda. Por isso, tentamos encontrar uma solução mais compatível. Aqui está:

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

Remainder(BigDecimal)retorna um BigDecimalcujo valor é (this % divisor). Se este for igual a zero, sabemos que não há ponto flutuante.

chaeschuechli
fonte
0

Minha solução simples:

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

Aqui está uma solução:

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