휴대용 isnan/isinf 기능을 만드는 방법
사용해왔습니다.isinf
,isnan
완벽하게 작동했던 리눅스 플랫폼의 기능들.하지만 이것이 OS-X에서 작동하지 않아서 사용하기로 결정했습니다.std::isinf
std::isnan
리눅스와 OS-X 둘 다에서 작동합니다.
하지만 인텔 컴파일러는 그것을 인식하지 못하고, http://software.intel.com/en-us/forums/showthread.php?t=64188 에 따르면 인텔 컴파일러의 버그인 것 같습니다.
그래서 이제 저는 번거롭지 않고 제 자신의 것을 정의하고자 합니다.isinf
,isnan
실행.
이것이 어떻게 이루어질 수 있는지 아는 사람?
편집:
이것을 내 소스코드로 만들어 버렸습니다.isinf
/isnan
일해
#include <iostream>
#include <cmath>
#ifdef __INTEL_COMPILER
#include <mathimf.h>
#endif
int isnan_local(double x) {
#ifdef __INTEL_COMPILER
return isnan(x);
#else
return std::isnan(x);
#endif
}
int isinf_local(double x) {
#ifdef __INTEL_COMPILER
return isinf(x);
#else
return std::isinf(x);
#endif
}
int myChk(double a){
std::cerr<<"val is: "<<a <<"\t";
if(isnan_local(a))
std::cerr<<"program says isnan";
if(isinf_local(a))
std::cerr<<"program says isinf";
std::cerr<<"\n";
return 0;
}
int main(){
double a = 0;
myChk(a);
myChk(log(a));
myChk(-log(a));
myChk(0/log(a));
myChk(log(a)/log(a));
return 0;
}
이 작업에 부스트를 사용할 수도 있습니다.
#include <boost/math/special_functions/fpclassify.hpp> // isnan
if( boost::math::isnan( ... ) .... )
나는 이것을 시도해 본 적은 없지만, 나는 생각할 것입니다.
int isnan(double x) { return x != x; }
int isinf(double x) { return !isnan(x) && isnan(x - x); }
효과가 있을 겁니다.더 좋은 방법이 있어야 할 것 같지만, 효과가 있을 겁니다.
이에 따르면 무한대는 쉽게 확인할 수 있습니다.
- 부호 = 양/음의 무한을 나타내는 0 또는 1비트입니다.
- 지수 = 모든 1비트.
- tantissa = 모두 0비트입니다.
NaN은 고유한 표현이 없기 때문에 조금 더 복잡합니다.
- 부호 = 0 또는 1.
- 지수 = 모든 1비트.
- tantissa = 모든 0비트를 제외한 모든 것(모든 0비트는 무한대를 나타냅니다.
아래는 이중 정밀 부동 소수점 케이스 코드입니다.단일 정밀도도 마찬가지로 쓸 수 있습니다(복수의 경우 지수가 11비트, 단식의 경우 8비트임을 기억하십시오).
int isinf(double x)
{
union { uint64 u; double f; } ieee754;
ieee754.f = x;
return ( (unsigned)(ieee754.u >> 32) & 0x7fffffff ) == 0x7ff00000 &&
( (unsigned)ieee754.u == 0 );
}
int isnan(double x)
{
union { uint64 u; double f; } ieee754;
ieee754.f = x;
return ( (unsigned)(ieee754.u >> 32) & 0x7fffffff ) +
( (unsigned)ieee754.u != 0 ) > 0x7ff00000;
}
구현은 매우 간단합니다(OpenCV 헤더 파일에서 가져온 것입니다).올바르게 선언해야 할 동일한 크기의 부호 없는 64비트 정수에 대한 결합을 사용합니다.
#if defined _MSC_VER
typedef unsigned __int64 uint64;
#else
typedef uint64_t uint64;
#endif
Visual Studio 2008에서 작동합니다.
#include <math.h>
#define isnan(x) _isnan(x)
#define isinf(x) (!_finite(x))
#define fpu_error(x) (isinf(x) || isnan(x))
안전을 위해서 fpu_error()를 사용하는 것을 추천합니다.어떤 숫자들은 isan()으로, 어떤 숫자들은 isinf()로, 그리고 어떤 숫자들은 isinf()로, 그리고 당신은 둘 다 안전해야 한다고 생각합니다.
테스트 코드는 다음과 같습니다.
double zero=0;
double infinite=1/zero;
double proper_number=4;
printf("isinf(infinite)=%d.\n",isinf(infinite));
printf("isinf(proper_number)=%d.\n",isinf(proper_number));
printf("isnan(infinite)=%d.\n",isnan(infinite));
printf("isnan(proper_number)=%d.\n",isnan(proper_number));
double num=-4;
double neg_square_root=sqrt(num);
printf("isinf(neg_square_root)=%d.\n",isinf(neg_square_root));
printf("isinf(proper_number)=%d.\n",isinf(proper_number));
printf("isnan(neg_square_root)=%d.\n",isnan(neg_square_root));
printf("isnan(proper_number)=%d.\n",isnan(proper_number));
출력은 다음과 같습니다.
isinf(infinite)=1.
isinf(proper_number)=0.
isnan(infinite)=0.
isnan(proper_number)=0.
isinf(neg_square_root)=1.
isinf(proper_number)=0.
isnan(neg_square_root)=1.
isnan(proper_number)=0.
isnan
는 현재 C++11의 일부이며, GCC++에 포함되어 있다고 생각하며, Apple LLVM.
적절한.#define
모래를#include
s는 적절한 해결책을 만들어야 합니다.
하지만 저는 nan detection 대신 nan이 발생하지 않도록 하는 것을 추천합니다.
인텔이 버그를 수정하거나 해결 방법을 제공할 때까지 기다리는 것이 이상적입니다 :-)
하지만 만약 당신이 탐지하고 싶다면NaN
그리고.Inf
IEEE754 값에서 정수(단일 정밀도인지 이중 정밀도인지에 따라 32비트 또는 64비트)로 매핑하고 지수 비트가 모두 1인지 확인합니다.이것은 그 두 경우를 나타냅니다.
당신은 구별할 수 있습니다.NaN
그리고.Inf
가수의 높은 차수의 비트를 확인함으로써.면 입니다.NaN
그렇지않으면Inf
.
+/-Inf
부호 비트에 의해 지시됩니다.
단일 정밀도(32비트 값)의 경우 부호는 상위 비트(b31), 지수는 다음 8비트(+23비트 가수)입니다.두 배의 정밀도를 위해 부호는 여전히 높은 차수의 비트이지만 지수는 11비트(가수의 경우 52비트 포함)입니다.
위키피디아는 모든 끔찍한 세부사항들을 가지고 있습니다.
다음 코드는 인코딩의 작동 방식을 보여줍니다.
#include <stdio.h>
static void decode (char *s, double x) {
long y = *(((long*)(&x))+1);
printf("%08x ",y);
if ((y & 0x7ff80000L) == 0x7ff80000L) {
printf ("NaN (%s)\n", s);
return;
}
if ((y & 0xfff10000L) == 0x7ff00000L) {
printf ("+Inf (%s)\n", s);
return;
}
if ((y & 0xfff10000L) == 0xfff00000L) {
printf ("-Inf (%s)\n", s);
return;
}
printf ("%e (%s)\n", x, s);
}
int main (int argc, char *argv[]) {
double dvar;
printf ("sizeof double = %d\n", sizeof(double));
printf ("sizeof long = %d\n", sizeof(long));
dvar = 1.79e308; dvar = dvar * 10000;
decode ("too big", dvar);
dvar = -1.79e308; dvar = dvar * 10000;
decode ("too big and negative", dvar);
dvar = -1.0; dvar = sqrt(dvar);
decode ("imaginary", dvar);
dvar = -1.79e308;
decode ("normal", dvar);
return 0;
}
출력:
sizeof double = 8
sizeof long = 4
7ff00000 +Inf (too big)
fff00000 -Inf (too big and negative)
fff80000 NaN (imaginary)
ffefdcf1 -1.790000e+308 (normal)
이 코드(방법은 아님)는 휴대성이 지나치게 높지 않은 긴 길이의 크기에 크게 의존한다는 것을 명심하십시오.하지만 정보를 얻기 위해 약간의 조작을 해야 한다면 이미 그 영역에 진입한 것입니다 :-)
덧붙여서, 저는 항상 Harald Schmidt의 IEEE754 변환기가 부동 소수점 분석에 매우 유용하다고 생각했습니다.
아주 간단한 IEEE 754-1985 호환 코드를 사용하면 됩니다.
static inline bool ISINFINITE( float a ) { return (((U32&) a) & 0x7FFFFFFFU) == 0x7F800000U; }
static inline bool ISINFINITEPOSITIVE( float a ) { return (((U32&) a) & 0xFFFFFFFFU) == 0x7F800000U; }
static inline bool ISINFINITENEGATIVE( float a ) { return (((U32&) a) & 0xFFFFFFFFU) == 0xFF800000U; }
static inline bool ISNAN( float a ) { return !ISINFINITE( a ) && (((U32&) a) & 0x7F800000U) == 0x7F800000U; }
static inline bool ISVALID( float a ) { return (((U32&) a) & 0x7F800000U) != 0x7F800000U; }
Boost가 이 기능을 제공한다고 Brubelsabs가 말했듯이, 여기 보고된 바와 같이, 사용하는 대신
if (boost::math::isnan(number))
이를 사용해야 합니다.
if ((boost::math::isnan)(number))
다음을 반환하는 C99 함수 fpclassify에 대해서는 아무도 언급하지 않은 것 같습니다.
FP_INFINITE, FP_NAN, FP_NORMAL, FP_SUBNORMAL, FP_ZERO 또는 구현 정의형 중 하나로 arg의 범주를 지정합니다.
이것은 비주얼 스튜디오에서 작동하지만 OS-X에 대해서는 잘 모릅니다.
다음 기사는 isnan에 대한 몇 가지 흥미로운 트릭을 가지고 있으며 inf: http://jacksondunstan.com/articles/983
이것은 osx에서 작동합니다.
#include <math.h>
휴대용일 수도 있고요
int isinf( double x ) { return x == x - 1; }
편집:
크리스가 지적했듯이 위의 것들은 큰 x로 실패할지도 모릅니다.
int isinf( double x ) { return x == x * 2; }
언급URL : https://stackoverflow.com/questions/2249110/how-do-i-make-a-portable-isnan-isinf-function
'programing' 카테고리의 다른 글
열거형에서 사용하는 정수형을 변경하는 방법(C++)? (0) | 2023.10.30 |
---|---|
jQuery, 전체 요소의 html을 가져옵니다. (0) | 2023.10.30 |
Git에서 tree-ish는 무엇을 의미합니까? (0) | 2023.10.25 |
C 유형 캐스트 및 추가 우선 순위 (0) | 2023.10.25 |
MariaDB SQL에서 정규식을 부정하려면 어떻게 해야 합니까? (0) | 2023.10.25 |