Controllare se float è un intero

Come posso verificare se una variabile float contiene un valore intero? Finora, ho usato:

 float f = 4.5886; if (f-(int)f == 0) printf("yes\n"); else printf("no\n"); 

Ma mi chiedo se c’è una soluzione migliore, o se questa ha qualche (o molti) inconvenienti.

A parte le belle risposte già date, puoi anche usare ceilf(f) == f o floorf(f) == f . Entrambe le espressioni restituiscono true se f è un numero intero. Restituiscono anche false per i NaN (i NaNs vengono sempre confrontati in modo non uguale ) e true per ± infinito, e non hanno il problema di traboccare il tipo intero usato per contenere il risultato troncato, perché floorf() / ceilf() restituisce float s.

Tieni presente che la maggior parte delle tecniche qui sono valide presumendo che l’errore di arrotondamento dovuto a calcoli precedenti non sia un fattore. Ad esempio potresti usare roundf , come questo:

 float z = 1.0f; if (roundf(z) == z) { printf("integer\n"); } else { printf("fraction\n"); } 

Il problema con questa e altre tecniche simili (come ceilf , casting a long , ecc.) È che, mentre funzionano alla grande per costanti di numeri interi, falliranno se il numero è il risultato di un calcolo che era sobject a errore di arrotondamento del punto. Per esempio:

 float z = powf(powf(3.0f, 0.05f), 20.0f); if (roundf(z) == z) { printf("integer\n"); } else { printf("fraction\n"); } 

Stampa “frazione”, anche se (3 1/20 ) 20 dovrebbe essere uguale a 3, perché il risultato del calcolo effettivo è stato 2.9999992847442626953125 .

Qualsiasi metodo simile, sia fmodf o qualsiasi altra cosa, è sobject a questo. Nelle applicazioni che eseguono calcoli complessi o inclinabili, di solito ciò che si vuole fare è definire un valore di “tolleranza” per ciò che costituisce un “numero intero” (questo vale per i confronti di uguaglianza in virgola mobile in generale). Spesso chiamiamo questa tolleranza epsilon . Ad esempio, diciamo che perdoniamo il computer fino a +/- 0,00001 errore di arrotondamento. Quindi, se stiamo testando z , possiamo scegliere un epsilon di 0.00001 e fare:

 if (fabsf(roundf(z) - z) <= 0.00001f) { printf("integer\n"); } else { printf("fraction\n"); } 

Non si vuole veramente usare ceilf qui perché eg ceilf(1.0000001) è 2 non 1, e ceilf(-1.99999999) è -1 non -2.

Se preferisci, puoi usare rintf al posto di roundf .

Scegli un valore di tolleranza appropriato per la tua applicazione (e sì, a volte la tolleranza zero è appropriata). Per ulteriori informazioni, consulta questo articolo sul confronto dei numeri in virgola mobile .

stdlib float modf (float x, float * ipart) si divide in due parti, controlla se restituisce il valore (parte frazionaria) == 0.

 if (fmod(f, 1) == 0.0) { ... } 

Non dimenticare math.h e libm .

 if (f <= LONG_MIN || f >= LONG_MAX || f == (long)f) /* it's an integer */ 

Non sono sicuro al 100%, ma quando lanci f per un int, e lo sottrai da f, credo che sia ricondotto a un float. Questo probabilmente non conta in questo caso, ma potrebbe presentare dei problemi lungo la linea se ci si aspetta che sia int per qualche motivo.

Non so se sia una soluzione migliore di per sé, ma potresti usare la matematica del modulo, ad esempio: float f = 4.5886; bool isInt; isInt = (f % 1.0 != 0) ? false : true; float f = 4.5886; bool isInt; isInt = (f % 1.0 != 0) ? false : true; a seconda del compilatore, potrebbe essere necessario o meno il .0 dopo l’1, di nuovo tutta la cosa dei cast impliciti entra in gioco. In questo codice, il valore bool isInt dovrebbe essere true se la destra del punto decimale è tutti zero e false altrimenti.

 #define twop22 (0x1.0p+22) #define ABS(x) (fabs(x)) #define isFloatInteger(x) ((ABS(x) >= twop22) || (((ABS(x) + twop22) - twop22) == ABS(x))) 

Bene, ho incontrato recentemente questo problema e sorprendentemente a trovare soluzioni su Internet per questo. Quindi ecco la mia soluzione. Ad esempio: se il valore è 3,00 e abbiamo solo bisogno di 3, allora dobbiamo controllare se dopo “.” ci sono zeri o no. Se tutto ciò può essere convertito in int, rimane mobile. Quindi includi questa funzione

 int isInt(float val) { int i = (int) val; if( i != val) return 0; // its not an integer else return 1; // is an integer } int main() { float i = 3.9; // not this is an example. if(isInt()) printf("%d", i); else printf("%f", i); return 0; } 

Spero che sia d’aiuto!

http://anandkhinvasara.com/check-whether-number-integer-float-c/