2011-08-27 47 views
16
float f = (float)'a'; 
if(f < 0){ 
} 
else if(f == 0){ 
} 
else if(f > 0){ 
} 
else{ 
    printf("NaN\n");               
} 

f如果它是NaN將不會大於/等於/小於0如何在c中生成NaN浮點數?

但如何生產這樣的f在第一位?

我嘗試過各種方法來產生NaN,但沒有工作..

+0

http://www.gnu.org/s/hello/manual/libc/Infinity-and-NaN.html –

+1

你可以使用一點C++嗎? C++有std :: numeric_limits的東西,其中包括用於安靜和信令NaN的常量。另外,你確定你的系統支持NaN嗎?因爲當你說0.0/0.0不是NaN時我真的很驚訝,我開始懷疑你的圖書館沒有按照你的想法設置。 –

回答

17

使用浮點數,0.0/0.0是不是一個錯誤「被零除」;它導致NaN

這個C程序打印-nan

#include <stdio.h> 

int main() 
{ 
    float x = 0.0/0.0; 
    printf("%f\n", x); 
    return 0; 
} 

在條款的外觀NaN像電腦,兩個「無效」的數字保留爲「信號」和「安靜」南(類似於兩個無效號碼保留正負無窮大)。 Wikipedia entry有關於NaN如何表示爲IEE浮點數的更多詳細信息。

+0

試過了,'NaN'沒有打印,所以不起作用。 –

+0

@Je Rog:我的不好,我已經解決了我的問題。 –

+0

@威廉,它的工作原理!但是'NaN'代表的是怎樣的?這意味着用於單精度和雙精度值的IEEE標準格式定義了一些無效值,可以用作'NaN',對吧? –

17

爲了產生楠,有一些方法:

1)手動生成(讀ieee754正確設置的比特)

2)使用宏。 GCC公開了一個宏NAN。它在math.h中定義

,檢查是否有楠的一般方法是檢查if (f == f)(這應該失敗NaN值)

對於南,在浮點表示的指數位都應該被設置爲1 (float由一個有符號位,一組指數位和一組尾數位組成)

+4

你也可以使用'isnan()'來檢查NaN(需要C99或(在unix系統上)相應的功能標誌,詳細信息請參見手冊頁) – bdonlan

+1

@bdonlan稍微OT,但它真的很奇怪python沒有引入isnan直到2.6 –

+0

我在我的工具集中找到NAN位/ nan.h。 – DarenW

3

從GNU GCC手冊math.h定義的宏允許您明確地將變量設置爲無窮大或NaN。既然這是C99的一部分,你可以使用下面的宏和我希望的其他c99兼容編譯器。

- 宏:float INFINITY 表示正無窮大的表達式。它等於數學運算產生的值,如1.0/0.0。 -INFINITY代表負無窮。

您可以通過將其與此宏進行比較來測試浮點值是否無限。但是,這不是建議;你應該使用isfinite宏代替。請參閱浮點類。

該宏是在ISO C99標準中引入的。

- Macro:float NAN 一個表達式表示「不是數字」的值。這個宏是GNU擴展,僅在支持「非數字」值的機器上可用,也就是說,在所有支持IEEE浮點的機器上。

您可以使用'#ifdef NAN'來測試機器是否支持NaN。 (當然,你必須安排GNU擴展是可見的,比如定義_GNU_SOURCE,然後你必須包含math.h.)

進一步的信息,你可以在這裏看到: http://www.gnu.org/s/hello/manual/libc/Infinity-and-NaN.html

+0

'NAN'宏不是GNU擴展(至少不會)。它已經在ISO C99標準中引入。因此,不是定義'_GNU_SOURCE',而是以某種形式的C99模式或更高版本(而不是C89)編譯就足夠了。 – vinc17

1

這適用於常量太(0/0會給VS編譯器錯誤):

const unsigned maxU = ~0; 
const float qNan = *((float*)&maxU); 
+0

至少有4個可移植性問題:有符號整數類型爲'〜',可能太短(例如在某些嵌入式系統上)的int,NaN表示和破壞的別名規則。有關詳細信息,請參閱[我的答案](http://stackoverflow.com/a/43496916/3782797)。 – vinc17

0

下面的C程序會產生NaN的。第二個聲明將導致NaN。

#include <stdio.h> 
#include <tchar.h> 
#include "math.h" 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    double dSQRTValue = sqrt(-1.00); 
    double dResult = -dSQRTValue; // This statement will result in a NaN. 
    printf("\n %lf", dResult); 

    return 0; 
} 

以下將是程序的輸出。

1.#QNAN0

1

既可以使用NAN宏,或者乾脆nan/nanf之一功能NaN值分配給變量。
檢查你是否正在處理一個nan值,你可以使用isnan()。 下面是一個例子:

#include <stdio.h> 
#include <math.h> 

int main(void) { 

    float a = NAN;//using the macro in math.h 
    float f = nanf("");//using the function version 
    double d = nan("");//same as above but for doubles! 

    printf("a = %f\nf = %f\nd = %f\n",a,f,d); 

    if(isnan(a)) 
     puts("a is a not a number!(NAN)\n"); 

    return 0; 
} 

運行上面的代碼段會給你這樣的輸出:自己

a = nan 
f = nan 
d = nan 
a is a not a number!(NAN) 

運行代碼:http://ideone.com/WWZBl8
瞭解更多信息:http://www.cplusplus.com/reference/cmath/NAN/

+0

爲什麼這篇文章被低估?! – Breeze

+0

這可能是因爲'nan'和'nanf'不是標準的C函數。 – skyking

+0

@skyking'nan'和'nanf' **是自1999年以來的標準ISO C函數**。 – MarkWeston

0

楠當我們編程時包含像0.0/0.0所述的值,如@Dan Cecile或sqrt(-1)所述。

1

對於託管的C實現,可以執行#include <math.h>並使用NAN宏(如果已定義)。例如,對於GCC,它由內建實現:(__builtin_nanf (""))

對於獨立C實現(在其上<math.h>頭可能不可用),或者當沒有定義NAN宏(這可能發生即使NaN的可被支撐),可以產生爲NaN具有浮點運算如0.0 / 0.0。但是,它可能有幾個問題。

首先,這樣的操作也會產生一個異常,在某些C實現上可能存在陷阱。我們可以確保它被計算在編譯時間:

static double my_nan = 0.0/0.0; 

另一個問題是,微軟的Visual C++(至少某些版本)嘗試在編譯時(以評估0.0 / 0.0即使這種表達是在任意的地方在代碼中)並且抱怨它的有效性。所以,這裏的解決方案是相反的一個:確保編譯器不會在編譯時評價它,這樣做:

static double zero = 0.0; 

,然後使用zero / zero。由於這些解決方案有衝突,因此可以使用specific macros上的預處理器指令(#if ...)來測試編譯器。

人們也可以選擇基於NaN編碼的解決方案,但也存在可移植性問題。首先,IEEE 754標準並沒有完全定義NaN的編碼,特別是區分安靜和信令NaN(和實際中硬件不同)的方式;信號NaNs會產生未定義的行爲。而且,IEEE 754標準沒有定義如何在存儲器中表示比特串,即可能需要檢測字節序。如果這些問題得到解決,則使用指針轉換的聯合或unsigned char的數組可以很好地獲得浮點類型。不要在其地址上使用帶有指針的整數進行類型雙擊,因爲這會破壞C別名規則。