2012-04-28 15 views
4

我試圖運行一些測試與轉換和浮動鑄件到其他類型,我想設置我的浮動變量爲nan的不同值。 「一個IEEE浮點標準單精度(32位)NaN的按位示例可能是:s111 1111 1axx xxxx xxxx xxxx xxxx xxxx其中s是符號(在應用程序中經常被忽略),a確定NaN的類型,x是一個額外的有效載荷(在應用程序中最常被忽略),如果a = 1,那麼它是一個安靜的NaN;如果a是零並且有效載荷不爲零,那麼它是一個信號NaN「如何手動設置相當於NaN的浮點數的位值?

基本上我想找到一種方法來設置有效載荷或xxxx的表示。有什麼辦法可以在c中做到這一點?

回答

8

您可以通過傳遞適當的串到C99 nan, nanf, nanl功能來控制「有效載荷」位,但這些只會產生安靜 NaN的,並且該字符串的解釋是未指定的(大部分實現把它當作一個十六進制數字)。

或者使用工會:

#ifndef __STDC_IEC_559__ 
#error "This program requires IEEE floating point arithmetic" 
#endif 

#include <stdint.h> 
#include <assert.h> 

static_assert(sizeof(float) == sizeof(uint32_t), 
    "This program requires float to be 32 bits exactly"); 

float nanf_with_payload_bits(uint32_t payload) 
{ 
    if (payload & 0x7FA00000) abort(); 

    union ieee_single { 
     float f; 
     uint32_t i; 
    } nan; 

    nan.i = 0x7FA00000 | payload; 
    return nan.f; 
} 

寫入工會的一個成員,然後從另一個讀取,當這兩種類型都完全一樣大小,不挑起C99 +勘誤未定義行爲。 (它是在C89中未定義的行爲,但大多數編譯器定義它做你期望的。它可能仍然是C++中的未定義行爲,我不確定;但是,大多數編譯器再次定義它做你會做的期望。)

如果您使用此函數創建信號 NaN的,要知道,C99/C11附件在他們的行爲被明確未定義F.

不要試圖打破的的i組件聯合成一個具有位域的結構。結構中的位字段的存儲器佈局是部分實現定義的並且部分未指定,並且特別地,位字段序列不必以與CPU字節順序相同的順序被打包到字中(或者實際上,妥善包裝)。


標準引用(所有C99):

  • 這種使用工會的只有不確定行爲:6.2.6.1p7; J.1
  • 結構內位域的佈局是不可預知的:6.2.6.1p1,2; 6.7.2.1p10,11,13; J.3.9
  • 信號NaN的行爲是未定義:F.2.1
+0

你是什麼意思,由排序瘋狂?我可能會遇到與此相關的問題。 – Chris 2012-04-28 17:59:47

+1

簡短的版本是,'struct'中的位域順序不一定與*其他任何*符合。然而,在所有現代系統中,'uint32_t'中的位順序將與'float'中的位順序相同(過去曾經有不同的計算機,但AFAIK沒有完全製造出來一段時間)。這個盒子的長版太長了。我不得不看到導致你有問題的代碼來說更多。建議您提出一個關於該問題的新問題並將其鏈接到此處。 – zwol 2012-04-28 18:14:00

+0

只是鏈接它:http://stackoverflow.com/questions/10366485/problems-casting-nan-floats-to-int謝謝! – Chris 2012-04-28 18:45:11

3

使用memcpy

int32_t i = 0x7FC00000; 
float f; 
memcpy(&f, &i, sizeof(f)); 

你也可以斷言,sizeof(f) == sizeof(i),但如果你知道花車IEEE那麼想必你也知道基本類型的大小。

3

有一種支持的方式可以在C中編寫安靜的NaN的有效載荷。

nan,nanf和nanl函數(math.h頭文件,1999 C規範的7.12.11.2節)接受字符串作爲參數。 strtof,strtod和strtold函數(stdlib.h頭文件的第7.20.1.3節)接受「NAN(字符序列)」形式的字符串。 fscanf和sscanf函數遵循strtod。但是,字符序列是以實現定義的方式解釋的。 (這意味着你的編譯器應該爲你提供指定解釋的文檔,有些編譯器不會遵守這個標準的要求。)

fprintf函數(stdio.h,7.19.6.1小節)可能會輸出一個字符串形式「NAN(字符序列)」與浮點格式(a,e,f,g)一樣,可以是printf和sprintf。該標準允許輸出沒有字符序列的「NAN」,所以這對許多編譯器不起作用。

由於解釋是實現定義的,所以您不應該期望它們是可移植的。它們通常用於調試等特殊用途。

相關問題