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?



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.


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


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.


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


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


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

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.



3

Voici une bonne solution:

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

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

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

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.


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.


0

Ma solution simple:

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

-1

Voici une solution:

float var = Your_Value;
if ((var - Math.floor(var)) == 0.0f)
{
    // var is an integer, so do stuff
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.