как я делаю портативную функцию isnan/isinf

Я использовал 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: "<

37
задан Yu Hao 17 August 2013 в 16:24
поделиться

4 ответа

Я не пробовал, но думаю, что

int isnan(double x) { return x != x; }
int isinf(double x) { return !isnan(x) && isnan(x - x); }

подойдет. Кажется, что должен быть лучший способ для isinf, но он должен работать.

21
ответ дан 27 November 2019 в 04:27
поделиться

Ну, в идеале, вы должны подождать, пока 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 Харальда Шмидта очень полезным для плавающих точечный анализ.

6
ответ дан 27 November 2019 в 04:27
поделиться

это работает на osx

#include <math.h>

, также это может быть переносимым,

int isinf( double x ) { return x == x - 1; }

редактировать:

как указал Крис, вышеупомянутое может не работать с большим x

int isinf( double x ) { return x == x * 2; }
-3
ответ дан 27 November 2019 в 04:27
поделиться

Это работает в 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.
7
ответ дан 27 November 2019 в 04:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: