So testen Sie, ob ein Double eine Ganzzahl ist


165

Ist das möglich?

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
}

Ich weiß, dass der Code wahrscheinlich nicht so aussieht, aber wie geht es?



1
Was würden Sie davon gewinnen? doubleund intwerden im Speicher unterschiedlich dargestellt, und Sie würden das eine oder andere basierend auf dem Kontext Ihrer Speicherbehandlung verwenden.
Makoto

@Legend, ich hätte das gleiche getan, wie Sie vorgeschlagen haben; Wissen Sie zufällig, wie die% 1 in Bezug auf die Effizienz mit der von anderen Benutzern vorgeschlagenen Math.floor (Variable) verglichen wird?
G. Bach

3
@ Makoto Es ist ein Programm, um pygatorische Tripel zu finden. Quadratwurzeln können manchmal doppelt sein, aber gleichzeitig können sie auch manchmal interger sein. Verstehst du was ich meine?
JXPheonix

@JXPheonix: Werte können also entweder ein Gleitkommawert oder ein ganzzahliger Wert sein. Macht Sinn.
Makoto

Antworten:


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

Dies prüft, ob der abgerundete Wert des Double mit dem Double identisch ist.

Ihre Variable kann einen int- oder double-Wert haben und hat Math.floor(variable)immer einen int-Wert. Wenn Ihre Variable also gleich ist, Math.floor(variable)muss sie einen int-Wert haben.

Dies funktioniert auch nicht, wenn der Wert der Variablen unendlich oder negativ unendlich ist, und fügt der Bedingung daher hinzu, dass die Variable nicht unendlich ist.


3
"Wenn das Argument NaN oder eine Unendlichkeit oder eine positive Null oder eine negative Null ist, ist das Ergebnis das gleiche wie das Argument." docs.oracle.com/javase/6/docs/api/java/lang/…
Tim Schmelter

2
@ TimSchmelter: guter Fang. Es ist auch erwähnenswert, dass NaN nicht gleich ist (einschließlich sich selbst), aber +/- Inf ist gleich sich selbst - es gibt also zwei Randfälle!
Maerics

Sowohl Skon als auch Fouad haben viel bessere Antworten gepostet.
Joel Christophel

@ JoelChristophel: Ich stimme nicht zu. Dies ist ein guter Weg, da das Risiko eines Typüberlaufs ausgeschlossen ist. Das einzige, was mir nicht gefallen hat, war die Behauptung, dass die Variable eine intIf- ifAuswertung war true.
Bathseba

@Bathsheba (Double.POSITIVE_INFINITY% 1) == 0 und sein negatives Gegenstück werden beide mit false bewertet.
Joel Christophel

222

Oder Sie können den Modulo-Operator verwenden:

(d % 1) == 0


2
Ich mag die Einfachheit dieser Lösung sehr. Es ist sowohl leicht zu lesen als auch zu implementieren.
Krispy

1
Sehr intuitive Lösung
Daniel San

3
Ist es in Bezug auf die Berechnung schneller als Math.rint(d)?
iTurki

2
Ja, das ist schön, aber beachten Sie, dass dies eine Java-Lösung ist und din C und C ++ für Negative nicht gut definiert ist .
Bathseba

4
In Sonar führt dies zu dem Problem "Gleichheitstests sollten nicht mit Gleitkommawerten durchgeführt werden."
Julio D

86

Guave : DoubleMath.isMathematicalInteger. (Offenlegung: Ich habe es geschrieben.) Oder, wenn Sie Guava noch nicht importieren, x == Math.rint(x)ist dies der schnellste Weg. rintist messbar schneller als flooroder ceil.


3
Wusste nichts über Math.rint. Du hast recht. Es ist viel schneller als Math.floor
Lenny Markus

Ist das Eng.Fouads Casting-Beispiel irgendwie vorzuziehen?
Joel Christophel

@ JoelChristophel: Ja. Nicht alle Doubles mit ganzzahligen Werten liegen im Bereich von int oder sogar long, sodass der Test nicht funktioniert.
Louis Wasserman

Erwischt. Dann ist (d% 1) == 0 noch gültig.
Joel Christophel

20
public static boolean isInt(double d)
{
    return d == (int) d;
}

6

Versuchen Sie es so,

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

beispielsweise:

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

daher 12,9 ist nicht ganzzahlig, dennoch

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

daher ist 12.0 eine ganze Zahl


3

Hier ist eine Version für Integerund 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;
    }
}

So konvertieren Sie Doublezu Integer:

Integer intVariable = variable.intValue();

3

Erwägen:

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

Dies bleibt bei Kern-Java und vermeidet einen Gleichheitsvergleich zwischen Gleitkommawerten ( ==), der als schlecht eingestuft wird. Dies isFinite()ist notwendig, ebenso rint()wie Durchgangs-Unendlichkeitswerte.



3

Hier ist eine gute Lösung:

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

Warum die (bool)Besetzung?
xdavidliu

1
@xdavidliu Das ist nicht nötig. Wir können es ignorieren.
Nitish

2

Ähnlich wie bei SkonJeets Antwort oben, aber die Leistung ist besser (zumindest in 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);
}

Eine korrektere Implementierung würde false zurückgeben und Sie müssten eine andere Methode schreiben, die int als Argument verwendet und true zurückgibt. : D
alfa

0

Sie können dies folgendermaßen versuchen: Ermitteln Sie den ganzzahligen Wert des Doppelten, subtrahieren Sie diesen vom ursprünglichen doppelten Wert, definieren Sie einen Rundungsbereich und testen Sie, ob die absolute Zahl des neuen doppelten Werts (ohne den ganzzahligen Teil) größer oder kleiner als Ihr Wert ist definierter Bereich. Wenn es kleiner ist, können Sie es beabsichtigen, es ist ein ganzzahliger Wert. Beispiel:

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

Wenn Sie d den Wert 33.15 zuweisen, gibt die Methode true zurück. Um bessere Ergebnisse zu erzielen, können Sie testRange nach eigenem Ermessen niedrigere Werte (als 0,0002) zuweisen.


0

Persönlich bevorzuge ich die einfache Modulo-Operationslösung in der akzeptierten Antwort. Leider mag SonarQube keine Gleichheitstests mit Gleitkommawerten, ohne eine runde Genauigkeit festzulegen. Deshalb haben wir versucht, eine konformere Lösung zu finden. Hier ist es:

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

Remainder(BigDecimal)gibt a zurück, BigDecimaldessen Wert ist (this % divisor). Wenn dies gleich Null ist, wissen wir, dass es keinen Gleitkomma gibt.


0

Meine einfache Lösung:

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

-1

Hier ist eine Lösung:

float var = Your_Value;
if ((var - Math.floor(var)) == 0.0f)
{
    // var is an integer, so do stuff
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.