Sprawdzanie, czy float jest liczbą całkowitą

Jak mogę sprawdzić, czy zmienna float zawiera wartość całkowitą? Jak na razie używam:

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

Ale zastanawiam się, czy jest lepsze rozwiązanie, czy to ma jakieś (lub wiele) wad.

Author: mskfisher, 2011-04-27

8 answers

Oprócz dobrze już udzielonych odpowiedzi, Możesz również użyć ceilf(f) == f LUB floorf(f) == f. Oba wyrażenia zwracają true, Jeśli f jest liczbą całkowitą. Zwracają równieżfalse dla Nan ( Nan zawsze porównuje nierówne ) i true dla ±nieskończoności i nie mają problemu z przepełnieniem typu integer używanego do przechowywania okrojonego wyniku, ponieważ floorf()/ceilf() return float s.

 61
Author: Marc Mutz - mmutz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:30:46

Należy pamiętać, że większość technik tutaj są ważne zakładając, że błąd zaokrągleń z powodu wcześniejszych obliczeń nie jest czynnikiem. Np. możesz użyć roundf, Tak:

float z = 1.0f;

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

Problem z tą i innymi podobnymi technikami (takimi jak ceilf, casting do long itp.) jest to, że podczas gdy działają one świetnie dla stałych liczb całkowitych, nie powiodą się, jeśli liczba jest wynikiem obliczeń, które były przedmiotem zmiennoprzecinkowego błędu zaokrąglania. Na przykład:

float z = powf(powf(3.0f, 0.05f), 20.0f);

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

Drukuje "ułamek", mimo że (31/20)20 powinno być równe 3, ponieważ rzeczywisty wynik obliczeń okazał się 2.9999992847442626953125.

Każda podobna metoda, czy to fmodf czy cokolwiek innego, podlega temu. W aplikacjach, które wykonują złożone lub podatne na zaokrąglenia obliczenia, zwykle to, co chcesz zrobić, to zdefiniować pewną wartość "tolerancji" dla tego, co stanowi "liczbę całkowitą" (dotyczy to porównań równości zmiennoprzecinkowej ogólnie). Często nazywamy to tolerancją epsilon. Na przykład, powiedzmy, że wybaczymy komputerowi błąd zaokrąglenia do +/- 0.00001. Następnie, jeśli testujemy z, możemy wybrać epsilon równy 0,00001 i wykonać:

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

Tak naprawdę nie chcesz używać ceilf tutaj, ponieważ np. ceilf(1.0000001) jest 2, a nie 1, a ceilf(-1.99999999) jest -1, a nie -2.

Możesz użyć rintf zamiast roundf jeśli wolisz.

Wybierz wartość tolerancji odpowiednią dla danego zastosowania (i tak, czasami odpowiednia jest zerowa tolerancja). Aby uzyskać więcej informacji, zapoznaj się z tym artykułem na temat porównywania liczb zmiennoprzecinkowych.

 14
Author: Jason C,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-13 09:34:58

Stdlib float modf (float x, float *ipart) dzieli się na dwie części, sprawdź czy wartość zwracana (część ułamkowa) = = 0.

 8
Author: DavidN,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-26 22:04:05
if (fmod(f, 1) == 0.0) {
  ...
}

Nie zapomnij math.h i libm.

 6
Author: Ignacio Vazquez-Abrams,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-26 22:05:17
if (f <= LONG_MIN || f >= LONG_MAX || f == (long)f) /* it's an integer */
 4
Author: R..,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-22 17:03:41

Nie jestem pewien na 100%, ale kiedy rzucisz f na int, i odjmiesz go od f, wierzę, że to będzie oddawanie cast z powrotem do float. To prawdopodobnie nie będzie miało znaczenia w tym przypadku, ale może stanowić problemy w dół linii, jeśli spodziewasz się, że jest int z jakiegoś powodu.

Nie wiem, czy jest to lepsze rozwiązanie per se, ale można użyć matematyki modułowej zamiast, na przykład: float f = 4.5886; bool isInt; isInt = (f % 1.0 != 0) ? false : true; w zależności od kompilatora możesz lub nie potrzebujesz .0 po 1, znowu cała ta ukryta sprawa wchodzi w Graj. W tym kodzie, bool isInt powinien być true, jeśli prawo punktu dziesiętnego to wszystkie zera, a false w przeciwnym razie.

 0
Author: Controllerface,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-26 22:25:55
#define twop22 (0x1.0p+22)
#define ABS(x) (fabs(x))
#define isFloatInteger(x) ((ABS(x) >= twop22) || (((ABS(x) + twop22) - twop22) == ABS(x)))
 0
Author: kanna,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-30 16:58:45

[1]} Cóż, ostatnio napotkałem ten problem i o dziwo znalazłem w Internecie jakieś rozwiązania tego problemu. Oto moje rozwiązanie. Dla NP-jeżeli wartość wynosi 3.00 i potrzebujemy tylko 3, to musimy sprawdzić czy po"."są zera lub nie. Jeśli wszystko może być przekonwertowane do int lub pozostaje float. Więc dołącz tę funkcję

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;
}
Mam nadzieję, że to pomoże!

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

 -2
Author: Anand Khinvasara,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-04 07:01:19