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?

JXPheonix
quelle
1
C # aber ähnlich in Java: stackoverflow.com/a/4077262/284240 ( Integer.MAX_VALUE )
Tim Schmelter
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.

Maxhud
quelle
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

SkonJeet
quelle
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.

Louis Wasserman
quelle
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;
}
Eng.Fouad
quelle
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

Sheldon
quelle
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();
irudyak
quelle
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.

simon.watts
quelle
3

Der beste Weg ist mit Modul Operator

if(val % 1 == 0)
Abdul Hafeez Khan
quelle
1
Können Sie bitte weitere Erklärungen zur Beantwortung hinzufügen? Vielen Dank!
Shanteshwar Inde
3

Hier ist eine gute Lösung:

if (variable == (int)variable) {
    //logic
}
Nitish
quelle
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()
edwardsayer
quelle
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
quelle
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.

Salvi94
quelle
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.

chaeschuechli
quelle
0

Meine einfache Lösung:

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

Hier ist eine Lösung:

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