1. 程式人生 > >浮點數NaN和INF(#IND, #INF)

浮點數NaN和INF(#IND, #INF)


參考:

NaN&INF定義

在一些情況會出現無效的浮點數,例如除0,例如負數求平方根等,像這類情況,獲取到的浮點數的值是無效的。

NaN 即 Not a Number         非數字

INF  即 Infinite            無窮大

通常無效浮點數的記憶體表示方法是:

根據IEEE 754標準:階碼全1,尾數全0表示無窮大INF。例如1.0/0.0

階碼全1,尾數非全0的表示無效數NaN。例如:求負數的平方根,例如0.0/0.0。

INF無窮大:在doulbe/float時的取值

float f = 0; (4位元組 1位符號位,8位指數,23位小數,指數偏移127)

*(UINT*)&f = 0x7F800000L;//正無窮(二進位制 [0111 1111] [1000 0000] [0000 0000] [0000 0000])

*(UINT*)&f = 0xFF800000L;//負無窮(二進位制 [1111 1111] [1000 0000] [0000 0000] [0000 0000])

double var = 0; (8位元組 1位符號位,11位指數,52位小數,指數偏移1023)

// 因為通常是little endian,所以通常修改其前後4個位元組

UINT* pVar = ((UINT*)&var) + 1;

*(pVar) = 0x7FF00000L;//正無窮

*(pVar) = 0xFFF00000L;//負無窮

常用的浮點數INF&NaN判斷方法:

1.

     Windows中,使用_isnan判斷NaN情況;使用!_isnan && !_finite判斷INF情況;使用!_finite判斷NaN和INF兩種情況

_isnan  //it returns a nonzero value if the argument x is a NaN;

_finite //It returns 0 if the argument is infinite or a NaN.

2.Linux中,使用insnan和isinf兩個函式分別判別兩種情況:

isNan

isInf

3.也可自己來寫:

int isNaN(double x) {return

x != x; }

#define _INF_DEFINE 1.0/0.0

int isInf(double n)

{

    static double pinf = 0.0;

    static double ninf = 0.0;

    if (pinf == 0.0) {

            pinf = _INF_DEFINE;

            ninf = -pinf;

    }

    return memcmp(&n, &pinf, sizeof(n)) == 0

            || memcmp(&n, &ninf, sizeof(n)) == 0;

}

依據:

1.   NaN是唯一與自身不等的浮點數型別,所以IsNan可以用 x != x來判斷。Anything compared with NAN is false, so NAN == NAN is false.

2.   INF階碼全1,尾數全0

還有一種借用isNan定義INF的方法

int isInf(double x) {return !isNaN(x) && isnan(x-x);}

依據:

1.   Inf – Inf得到的為NaN

附一段測試程式碼

#include "stdio.h"

void ViewHex(double x)
{
	unsigned int* pUInt = ((unsigned int*)(&x));
	printf("0x%08X  ", *pUInt);
	pUInt++;
	printf("0x%08X\n", *pUInt);
}
int main()
{
	double a = 1.0/0.0;
	double b = 0.0/0.0;
	double c = a-a;
	printf("%f\n%f\n%f\n", a, b, c);
	printf("%f\n%f\n%f\n", -a, -b, -c);
	ViewHex(a);
	ViewHex(b);
	ViewHex(c);
	ViewHex(-a);
	ViewHex(-b);
	ViewHex(-c);
	getchar();
        return 0;
}

// 測試輸出(執行環境: window 編譯程式:mingw/gcc)

inf

nan

nan

-inf

nan

nan

0x00000000 0x7FF00000

0x00000000 0xFFF80000

0x00000000 0xFFF80000

0x00000000 0xFFF00000

0x00000000 0x7FF80000

0x00000000 0x7FF80000