Я использовал isinf
, isnan
функции на платформах Linux, которые работали отлично. Но это не работало над OS X, таким образом, я решил использовать std::isinf
std::isnan
который работает и над Linux и над OS X.
Но компилятор Intel не распознает его, и я предполагаю, что это - ошибка в компиляторе Intel согласно http://software.intel.com/en-us/forums/showthread.php?t=64188
Таким образом, теперь я просто хочу избежать стычки и определить мое собственное isinf
, isnan
реализация.
Кто-либо знает, как это могло быть сделано?
править:
Я закончил тем, что делал это в своем исходном коде для того, чтобы сделать isinf
/isnan
работа
#include
#include
#ifdef __INTEL_COMPILER
#include
#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: "<
Я не пробовал, но думаю, что
int isnan(double x) { return x != x; }
int isinf(double x) { return !isnan(x) && isnan(x - x); }
подойдет. Кажется, что должен быть лучший способ для isinf, но он должен работать.
Ну, в идеале, вы должны подождать, пока Intel исправит ошибку или предложит обходной путь: -)
Но если вы хотите обнаружить NaN
и Inf
из значений IEEE754, сопоставьте его с целым числом (32 или 64 бит в зависимости от того, одинарная или двойная точность) и проверьте, все ли биты экспоненты равны 1. Это указывает на эти два случая. .
Вы можете различить NaN
и Inf
, проверив старший бит мантиссы. Если это 1, это NaN
, иначе Inf
.
+/- Inf
определяется битом знака.
Для одинарной точности (32-битные значения) знаком является старший бит (b31), экспонента - следующие восемь битов (плюс 23-битная мантисса). Для двойной точности знак по-прежнему является старшим битом, но показатель степени равен одиннадцати битам (плюс 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)
Просто имейте в виду, что этот код (но не метод) во многом зависит от размеров ваших длинных позиций, что не является слишком переносимым. Но, если вам нужно потрудиться, чтобы получить информацию, вы уже вошли на эту территорию: -)
Кстати, я всегда находил конвертер IEEE754 Харальда Шмидта очень полезным для плавающих точечный анализ.
это работает на osx
#include <math.h>
, также это может быть переносимым,
int isinf( double x ) { return x == x - 1; }
редактировать:
как указал Крис, вышеупомянутое может не работать с большим x
int isinf( double x ) { return x == x * 2; }
Это работает в 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 (). Я считаю, что некоторые числа подбираются с помощью isnan (), а некоторые - с помощью 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.