Jak sprawdzić, czy double jest liczbą całkowitą


165

Czy da się to zrobić?

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
}

Wiem, że kod prawdopodobnie nie działa w ten sposób, ale jak to działa ?



1
Co byś z tego zyskał? doublei intsą reprezentowane w pamięci w różny sposób, a używałbyś jednego lub drugiego w zależności od kontekstu, w jakim operujesz pamięcią.
Makoto

@Legend, zrobiłbym to samo, co sugerowałeś; czy przypadkiem wiesz, jak% 1 porównuje wydajność pod względem wydajności z Math.floor (zmienną) sugerowaną przez innych użytkowników?
G. Bach

3
@Makoto To program do wyszukiwania trójek pigatorejskich. Pierwiastki kwadratowe mogą czasami być podwójne, ale jednocześnie czasami mogą być intergerami. Rozumiesz o co mi chodzi?
JXPheonix

@JXPheonix: Więc wartości mogą być wartościami zmiennoprzecinkowymi lub całkowitymi. Ma sens.
Makoto

Odpowiedzi:


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

Sprawdza, czy zaokrąglona w dół wartość double jest taka sama jak double.

Twoja zmienna może mieć wartość int lub double i Math.floor(variable)zawsze mieć wartość int, więc jeśli zmienna jest równa, Math.floor(variable)to musi mieć wartość int.

To również nie działa, jeśli wartość zmiennej jest nieskończona lub ujemna nieskończona, dlatego do warunku dodaje się „tak długo, jak zmienna nie jest nieskończona”.


3
„Jeśli argumentem jest NaN lub nieskończoność lub dodatnie zero lub ujemne zero, to wynik jest taki sam jak argument”. docs.oracle.com/javase/6/docs/api/java/lang/…
Tim Schmelter

2
@TimSchmelter: dobry chwyt. Warto również zauważyć, że NaN nie jest równe żadnemu (w tym sobie), ale +/- Inf jest sobie równe - więc są dwa skrajne przypadki!
maerics

Zarówno Skon, jak i Fouad opublikowali znacznie lepsze odpowiedzi.
Joel Christophel

@JoelChristophel: Nie zgadzam się. To dobry sposób, ponieważ eliminuje ryzyko przepełnienia tekstu. Jedyne, co mi się nie podobało, to stwierdzenie, że zmienna jest wartością, intjeśli ifwartości true.
Batszeba

@Bathsheba (Double.POSITIVE_INFINITY% 1) == 0 i jego ujemny odpowiednik dają wynik fałszywy.
Joel Christophel

222

Lub możesz użyć operatora modulo:

(d % 1) == 0


2
Naprawdę podoba mi się prostota tego rozwiązania. Jest zarówno łatwy do odczytania, jak i do wdrożenia.
krispy

1
Bardzo intuicyjne rozwiązanie
Daniel San

3
Jeśli chodzi o obliczenia, czy jest szybszy niż Math.rint(d)?
iTurki

2
Tak, to fajne, ale zauważ dobrze, że jest to rozwiązanie Java i nie jest dobrze zdefiniowane jako negatywne dw C i C ++.
Batszeba

4
W programie Sonar powoduje to problem „Testy równości nie powinny być wykonywane z wartościami zmiennoprzecinkowymi”.
Julio D,

86

Guawa: DoubleMath.isMathematicalInteger. (Ujawnienie: napisałem to.) Lub, jeśli jeszcze nie importujesz guawy, x == Math.rint(x)jest to najszybszy sposób na zrobienie tego; rintjest mierzalnie szybszy niż floorlub ceil.


3
Nie wiedziałem o Math.rint Masz rację. Jest znacznie szybszy niż Math.floor
Lenny Markus

Czy jest to w jakiś sposób lepsze od przykładu castingowego inż. Fouada?
Joel Christophel

@JoelChristophel: Tak. Nie wszystkie dublety z wartościami całkowitymi mieszczą się w zakresie int, a nawet long, więc ten test na nich nie zadziała.
Louis Wasserman,

Mam cię. Wtedy (d% 1) == 0 jest nadal ważne.
Joel Christophel


6

Spróbuj w ten sposób

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

na przykład:

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

stąd 12,9 nie jest jednak liczbą całkowitą

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

stąd 12,0 jest liczbą całkowitą


3

Oto wersja dla Integeri 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;
    }
}

Aby przekonwertować Doublena Integer:

Integer intVariable = variable.intValue();

3

Rozważać:

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

To trzyma się rdzenia Javy i pozwala uniknąć porównania równości między wartościami zmiennoprzecinkowymi ( ==), które są uważane za złe. Jest isFinite()to konieczne, podobnie jak rint()wartości nieskończoności.



3

Oto dobre rozwiązanie:

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

dlaczego (bool)obsada?
xdavidliu

1
@xdavidliu Nie ma takiej potrzeby. Możemy to zignorować.
Nitish

2

Podobna do odpowiedzi SkonJeeta powyżej, ale wydajność jest lepsza (przynajmniej w Javie):

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

Bardziej poprawna implementacja zwróciłaby false i musiałbyś napisać inną metodę, która przyjmuje int jako argument i zwraca true. : D
alfa

0

możesz spróbować w ten sposób: pobierz wartość całkowitą double, odejmij ją od pierwotnej wartości double, zdefiniuj zakres zaokrąglania i sprawdź, czy liczba bezwzględna nowej wartości double (bez części całkowitej) jest większa lub mniejsza niż twoja zdefiniowany zakres. jeśli jest mniejszy, możesz zamierzyć, że jest to wartość całkowita. Przykład:

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

Jeśli przypiszesz d wartość 33,15, metoda zwróci wartość true. Aby uzyskać lepsze wyniki, możesz według własnego uznania przypisać niższe wartości testRange (jako 0,0002).


0

Osobiście wolę proste rozwiązanie obsługi modulo w przyjętej odpowiedzi. Niestety SonarQube nie lubi testów równości z zmiennoprzecinkowymi bez ustawiania okrągłej precyzji. Dlatego staraliśmy się znaleźć bardziej zgodne rozwiązanie. Oto ona:

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

Remainder(BigDecimal)zwraca a, BigDecimalktórego wartość to (this % divisor). Jeśli ta jest równa zero, wiemy, że nie ma zmiennoprzecinkowego.


0

Moje proste rozwiązanie:

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

-1

Oto rozwiązanie:

float var = Your_Value;
if ((var - Math.floor(var)) == 0.0f)
{
    // var is an integer, so do stuff
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.