Comment tester si un double est un entier

166

Est-il possible de faire cela?

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
}

Je sais que le code ne va probablement pas quelque chose comme ça, mais comment n'aller?

JXPheonix
la source
1
C # mais similaire en Java: stackoverflow.com/a/4077262/284240 ( Integer.MAX_VALUE )
Tim Schmelter
1
Que gagneriez-vous de cela? doubleet intsont représentés en mémoire différemment, et vous utiliseriez l'un ou l'autre en fonction du contexte de votre gestion de la mémoire.
Makoto
@Legend, j'aurais fait la même chose que vous avez suggéré; savez-vous par hasard comment le% 1 se compare en termes d'efficacité au Math.floor (variable) suggéré par d'autres utilisateurs?
G. Bach
3
@Makoto C'est un programme pour trouver des triplets pygatoriens. Les racines carrées peuvent parfois être doubles, mais en même temps, elles peuvent aussi parfois être des intergers. Vous comprenez ce que je veux dire?
JXPheonix
@JXPheonix: Les valeurs peuvent donc être soit une valeur à virgule flottante, soit une valeur entière. Logique.
Makoto

Réponses:

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

Cela vérifie si la valeur arrondie du double est la même que celle du double.

Votre variable peut avoir une valeur int ou double et a Math.floor(variable)toujours une valeur int, donc si votre variable est égale à Math.floor(variable)alors elle doit avoir une valeur int.

Cela ne fonctionne pas non plus si la valeur de la variable est infinie ou infinie négative, ajoutant donc «tant que la variable n'est pas infinie» à la condition.

maxhud
la source
3
"Si l'argument est NaN ou un infini ou un zéro positif ou un zéro négatif, alors le résultat est le même que l'argument." docs.oracle.com/javase/6/docs/api/java/lang/…
Tim Schmelter
2
@TimSchmelter: bonne prise. Il convient également de noter que NaN n'est égal à rien (y compris lui-même) mais +/- Inf est égal à lui-même - il y a donc deux cas extrêmes!
maerics
Skon et Fouad ont affiché de bien meilleures réponses.
Joel Christophel
@JoelChristophel: Je ne suis pas d'accord. C'est un bon moyen car il élimine le risque de dépassement de type. La seule chose que je n'aimais pas, c'était l'affirmation selon laquelle la variable était un intif the ifévalue à true.
Bathsheba
@Bathsheba (Double.POSITIVE_INFINITY% 1) == 0 et son équivalent négatif sont tous deux évalués à faux.
Joel Christophel
223

Ou vous pouvez utiliser l'opérateur modulo:

(d % 1) == 0

SkonJeet
la source
2
J'adore la simplicité de cette solution. C'est à la fois facile à lire et à mettre en œuvre.
krispy
1
Solution très intuitive
Daniel San
3
En termes de calcul, est-ce plus rapide que Math.rint(d)?
iTurki
2
Oui c'est bien, mais notez bien qu'il s'agit d'une solution Java et qu'elle n'est pas bien définie pour les négatifs den C et C ++.
Bathsheba
4
Dans Sonar, cela produit un problème "Les tests d'égalité ne doivent pas être effectués avec des valeurs à virgule flottante."
Julio D
86

Goyave: DoubleMath.isMathematicalInteger. (Divulgation: je l'ai écrit.) Ou, si vous x == Math.rint(x)n'importez pas déjà Guava, c'est le moyen le plus rapide de le faire; rintest sensiblement plus rapide que floorou ceil.

Louis Wasserman
la source
3
Je ne savais pas pour Math.rint Vous avez raison. C'est beaucoup plus rapide que Math.floor
Lenny Markus
Est-ce préférable à l'exemple de casting de l'ingénieur Fouad?
Joel Christophel
@JoelChristophel: Oui. Tous les doubles avec des valeurs entières ne sont pas dans la plage de int, ou même longs, de sorte que le test ne fonctionnera pas sur eux.
Louis Wasserman
Je t'ai eu. Alors (d% 1) == 0 est toujours valide.
Joel Christophel
20
public static boolean isInt(double d)
{
    return d == (int) d;
}
Ing. Fouad
la source
6

Essayez de cette façon,

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

par exemple:

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

donc 12,9 n'est pas un entier, néanmoins

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

donc 12,0 est un entier

Sheldon
la source
3

Voici une version pour Integeret 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;
    }
}

Pour convertir Doubleen Integer:

Integer intVariable = variable.intValue();
irudyak
la source
3

Considérer:

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

Cela colle au noyau Java et évite une comparaison d'égalité entre les valeurs en virgule flottante ( ==) qui est considérée comme mauvaise. Le isFinite()est nécessaire, tout comme les rint()valeurs infinies.

simon.watts
la source
3

Le meilleur moyen est d'utiliser un opérateur de module

if(val % 1 == 0)
Abdul Hafeez Khan
la source
1
pouvez-vous s'il vous plaît ajouter plus d'explications pour répondre? Merci!
Shanteshwar Inde
3

Voici une bonne solution:

if (variable == (int)variable) {
    //logic
}
Nitish
la source
pourquoi le (bool)casting?
xdavidliu le
1
@xdavidliu Pas besoin de ça. Nous pouvons l'ignorer.
Nitish
2

Similaire à la réponse de SkonJeet ci-dessus, mais les performances sont meilleures (au moins en java):

Double zero = 0d;    
zero.longValue() == zero.doubleValue()
Edwardsayer
la source
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
la source
Une implémentation plus correcte renverrait false et vous devrez écrire une autre méthode qui prend int comme argument et renvoie true. : D
alfa
0

vous pouvez essayer de cette manière: obtenir la valeur entière du double, soustraire celle-ci de la valeur double d'origine, définir une plage d'arrondi et tester si le nombre absolu de la nouvelle valeur double (sans la partie entière) est plus grand ou plus petit que votre plage définie. s'il est plus petit, vous pouvez avoir l'intention que ce soit une valeur entière. Exemple:

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 vous affectez à d la valeur 33,15, la méthode renvoie true. Pour obtenir de meilleurs résultats, vous pouvez attribuer des valeurs inférieures à testRange (comme 0,0002) à votre discrétion.

Salvi94
la source
0

Personnellement, je préfère la solution d'opération modulo simple dans la réponse acceptée. Malheureusement, SonarQube n'aime pas les tests d'égalité avec des points flottants sans définir une précision ronde. Nous avons donc essayé de trouver une solution plus conforme. C'est ici:

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

Remainder(BigDecimal)renvoie un BigDecimaldont la valeur est (this % divisor). Si celui-ci est égal à zéro, nous savons qu'il n'y a pas de virgule flottante.

chaeschuechli
la source
0

Ma solution simple:

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

Voici une solution:

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