Come verificare se un doppio è un numero intero


166

È possibile farlo?

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
}

So che il codice probabilmente non va qualcosa di simile, ma come si fa a finire?



1
Cosa guadagneresti da questo? doublee intsono rappresentati nella memoria in modo diverso e useresti l'uno o l'altro in base al contesto della tua gestione della memoria.
Makoto,

@Legend, avrei fatto lo stesso che hai suggerito; sapete per caso come% 1 paragona l'efficienza in termini di efficienza al Math.floor (variabile) suggerito da altri utenti?
G. Bach

3
@Makoto È un programma per trovare triple triple. Le radici quadrate possono talvolta essere doppie, ma allo stesso tempo possono anche essere interger. Capisci cosa intendo?
JXPheonix,

@JXPheonix: Quindi i valori possono essere sia un valore a virgola mobile o un valore intero. Ha senso.
Makoto,

Risposte:


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

Questo controlla se il valore arrotondato per difetto del doppio è uguale al doppio.

La tua variabile può avere un valore int o double e Math.floor(variable)ha sempre un valore int, quindi se la tua variabile è uguale a Math.floor(variable)allora deve avere un valore int.

Anche questo non funziona se il valore della variabile è infinito o infinito negativo, quindi aggiungendo "fintanto che la variabile non è definita" alla condizione.


3
"Se l'argomento è NaN o infinito o zero positivo o zero negativo, il risultato è lo stesso dell'argomento." docs.oracle.com/javase/6/docs/api/java/lang/…
Tim Schmelter

2
@TimSchmelter: buona cattura. Vale anche la pena notare che NaN non è uguale a nulla (incluso se stesso) ma +/- Inf è uguale a se stesso - quindi ci sono due casi limite!
Maerici,

Sia Skon che Fouad hanno pubblicato risposte molto migliori.
Joel Christophel,

@JoelChristophel: Non sono d'accordo. Questo è un buon modo in quanto elimina il rischio di overflow del tipo. L'unica cosa che non mi è piaciuta è stata l'affermazione che la variabile era un intse la ifvaluta true.
Bathsheba,

@Bathsheba (Double.POSITIVE_INFINITY% 1) == 0 e la sua controparte negativa valutano entrambi come falsi.
Joel Christophel,

223

Oppure potresti usare l'operatore modulo:

(d % 1) == 0


2
Amo davvero la semplicità di questa soluzione. È sia facile da leggere che da implementare.
Krispy,

1
Soluzione molto intuitiva
Daniel San,

3
In termini di calcolo, è più veloce di Math.rint(d)?
iTurki,

2
Sì, questo è carino, ma nota bene che questa è una soluzione Java e non è ben definita per il negativo din C e C ++.
Bathsheba,

4
In Sonar, questo produce un problema "I test di uguaglianza non dovrebbero essere fatti con valori in virgola mobile".
Julio D,

86

Guava: DoubleMath.isMathematicalInteger. (Divulgazione: l'ho scritto.) Oppure, se non stai già importando Guava, x == Math.rint(x)è il modo più veloce per farlo; rintè misurabilmente più veloce di flooro ceil.


3
Non sapevo di Math.rint Hai ragione. È molto più veloce di Math.floor
Lenny Markus,

È in qualche modo preferibile all'esempio di casting di Eng.Fouad?
Joel Christophel,

@JoelChristophel: Sì. Non tutti i doppi con valori interi sono compresi nell'intervallo di int o anche lungo, quindi il test non funzionerà su di essi.
Louis Wasserman,

Gotcha. Quindi (d% 1) == 0 è ancora valido.
Joel Christophel,

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

6

Prova in questo modo,

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

per esempio:

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

quindi 12.9 non è intero, tuttavia

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

quindi 12.0 è intero


3

Ecco una versione per Integere 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;
    }
}

Per convertire Doublein Integer:

Integer intVariable = variable.intValue();

3

Tener conto di:

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

Questo si attacca al core Java ed evita un confronto di uguaglianza tra valori in virgola mobile ( ==) che viene considerato male. Il isFinite()occorre come rint()sarà pass-through valori sfioro.



3

Ecco una buona soluzione:

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

perché il (bool)cast?
xdavidliu,

1
@xdavidliu Non è necessario. Possiamo ignorarlo.
Nitish

2

Simile alla risposta di SkonJeet sopra, ma le prestazioni sono migliori (almeno 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);
}

Un'implementazione più corretta restituire false e dovresti scrivere un altro metodo che accetta int come argomento e restituisce true. : D
alfa,

0

si potrebbe provare in questo modo: ottenere il valore intero del doppio, sottrarlo dal doppio valore originale, definire un intervallo di arrotondamento e verificare se il numero assoluto del nuovo valore doppio (senza la parte intera) è maggiore o minore del valore intervallo definito. se è più piccolo puoi intenderlo è un valore intero. Esempio:

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

Se si assegna a d il valore 33.15 il metodo restituisce true. Per ottenere risultati migliori è possibile assegnare valori più bassi a testRange (come 0.0002) a propria discrezione.


0

Personalmente, preferisco la semplice soluzione operativa modulo nella risposta accettata. Sfortunatamente, a SonarQube non piacciono i test di uguaglianza con punti mobili senza impostare una precisione circolare. Quindi abbiamo cercato di trovare una soluzione più conforme. Ecco qui:

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

Remainder(BigDecimal)restituisce un BigDecimalvalore di cui è (this % divisor). Se questo è uguale a zero, sappiamo che non esiste un punto mobile.


0

La mia soluzione semplice:

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

-1

Ecco una soluzione:

float var = Your_Value;
if ((var - Math.floor(var)) == 0.0f)
{
    // var is an integer, so do stuff
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.