developer tip

float가 정수인지 확인

optionbox 2020. 11. 18. 08:56
반응형

float가 정수인지 확인


float변수에 정수 값이 포함되어 있는지 어떻게 확인할 수 있습니까? 지금까지 다음을 사용했습니다.

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

그러나 더 나은 해결책이 있는지 또는 이것이 어떤 (또는 많은) 단점이 있는지 궁금합니다.


이미 주어진 훌륭한 답변 외에도 ceilf(f) == f또는 을 사용할 수도 있습니다 floorf(f) == f. 두 표현식 모두 정수 true이면 반환 합니다 f. 또한 falseNaN ( NaN은 항상 같지 않음을 비교 함 ) 및 true± 무한대에 대해 반환 하며 floorf()/ ceilf()return floats 때문에 잘린 결과를 유지하는 데 사용되는 정수 유형을 오버플로하는 문제가 없습니다 .


여기에있는 대부분의 기술은 이전 계산으로 인한 반올림 오류가 요인이 아니라는 가정하에 유효합니다. 예를 들어 다음 과 같이 사용할 있습니다 roundf.

float z = 1.0f;

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

이 기술과 다른 유사한 기술 (예 : ceilf,으로 캐스팅 long등)의 문제점은 정수 상수에 대해서는 잘 작동하지만 숫자가 부동 소수점 반올림에 따른 계산의 결과이면 실패한다는 것입니다. -off 오류. 예를 들면 :

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

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

실제 계산 결과가 2.9999992847442626953125 가 되었기 때문에 (3 1/20 ) 20 은 3과 같아야 하지만 "fraction"을 인쇄 합니다 .

비슷한 방법 fmodf이든지간에 이것의 대상이됩니다. 복잡하거나 반올림하기 쉬운 계산을 수행하는 응용 프로그램에서 일반적으로 원하는 것은 "정수"를 구성하는 항목에 대해 "공차"값을 정의하는 것입니다 (일반적으로 부동 소수점 같음 비교에 적용됨). 우리는 종종이 공차를 엡실론 이라고 부릅니다 . 예를 들어, 최대 +/- 0.00001 반올림 오류에 대해 컴퓨터를 용서한다고 가정 해 보겠습니다. 그런 다음 테스트하는 경우 z0.00001의 엡실론을 선택하고 다음을 수행 할 수 있습니다.

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

ceilf예를 들어 ceilf(1.0000001)1 ceilf(-1.99999999)이 아닌 2 이고 -2가 아닌 -1 이기 때문에 여기서 사용하고 싶지 않습니다.

원하는 경우 rintf대신 사용할 수 있습니다 roundf.

응용 프로그램에 적합한 공차 값을 선택하십시오 (예, 경우에 따라 공차가 0 인 경우도 있음). 자세한 내용은 부동 소수점 숫자 비교 에 대한이 도움말을 참조하세요 .


stdlib float modf (float x, float * ipart)는 두 부분으로 나뉘어 반환 값 (분수 부분) == 0인지 확인합니다.


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

잊지 마세요 math.hlibm.


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

100 % 확실하지는 않지만 f를 int로 캐스트하고 f에서 빼면 float로 다시 캐스트되고 있다고 생각합니다. 이것은 아마도이 경우 중요하지 않을 것이지만 어떤 이유로 int가 될 것으로 예상한다면 문제가 발생할 수 있습니다.

그 자체로 더 나은 솔루션인지는 모르겠지만 대신 모듈러스 수학을 사용할 수 있습니다. 예를 들어, float f = 4.5886; bool isInt; isInt = (f % 1.0 != 0) ? false : true; 컴파일러에 따라 1 이후에 .0이 필요할 수도 있고 필요하지 않을 수도 있고, 다시 전체 암시 적 캐스트가 작동합니다. 이 코드에서 bool isInt는 소수점의 오른쪽이 모두 0이면 true이고 그렇지 않으면 false 여야합니다.


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

참고 URL : https://stackoverflow.com/questions/5796983/checking-if-float-is-an-integer

반응형