2008-10-24 18 views
31

在C++中使用NaNs的最佳方式是什麼?在C++中使用NaN?

我發現std::numeric_limits<double>::quiet_NaN()std::numeric_limits<double>::signaling_NaN()。我想使用signaling_NaN如下來表示一個未初始化的變量:

double diameter = std::numeric_limits<double>::signaling_NaN(); 

然而,這信號(引發一個例外)上的分配。我希望它在使用上引發異常,而不是分配。

有沒有辦法使用signaling_NaN沒有對轉讓引發異常? signaling_NaN是否有一個很好的便攜式替代品,在使用時會引發浮點異常?

+0

嗯...我正在玩這個,因爲我現在很好奇,但我不能讓我的異常。你做了什麼來獲得例外? – 2008-10-25 00:08:52

+0

@JeffreyMartinez這不是一個正常的C++異常,如果這就是你的想法。這是一個浮點異常:請參閱[此處]的註釋(http://en.cppreference.com/w/cpp/numeric/fenv)。 – bames53 2012-11-05 15:55:23

回答

11

尋找到這個多一些之後,它看起來像signaling_NaN是無用的規定。如果啓用了浮點異常,那麼調用它就像處理NaN信號一樣,因此它立即引發異常。如果禁用浮點異常,那麼處理信號NaN會自動將其降級爲安靜的NaN,因此signaling_NaN無論如何都不起作用。

Menkboy's code作品,但試圖使用信號NaN運行到其他的問題:有沒有可移植的方法來啓用或禁用浮點異常(如提到herehere),如果你依靠的例外被啓用,第三第三方代碼可能會禁用它們(如here所述)。

所以它看起來像Motti's solution確實是最好的選擇。

3

你可以寫一個信號NaN考慮的變量,而不引發異常像這樣的東西(注:未經測試)

void set_snan(double &d) 
{ 
    long long *bits = (long long *)&d; 
    *bits = 0x7ff0000080000001LL; 
} 

它會工作最多的地方,但沒有,它不是100%的便攜性。

3

好,既安靜和信令楠定義照顧,我真的不能做任何區別。

你可以使用在這些功能你自己使用的代碼,也許它阻止一個異常的方式,但看到這兩個功能也不例外,我認爲這可能與別的東西。

如果您想直接分配楠:

double value = _Nan._Double; 
9

什麼信號NAN的意思是,當CPU遇到它的信號被觸發,(因此得名)。如果要檢測未初始化的變量,則在編譯器中提高警告級別通常會檢測到所有使用未初始化值的路徑。如果做不到這一點,你可以使用存儲如果值初始化一個布爾說一個包裝類:

template <class T> 
class initialized { 
    T t; 
    bool is_initialized; 
public: 
    initialized() : t(T()), is_initialized(false) { } 
    initialized(const T& tt) : t(tt), is_initialized(true) { } 
    T& operator=(const T& tt) { t = tt; is_initialized = true; return t; } 
    operator T&() { 
     if (!is_initialized) 
      throw std::exception("uninitialized"); 
     return t; 
    } 
}; 
3

答案很簡單: 做這樣的事情在頭文件,並用它在其他地方:如果你希望做一些對他們操作的最好寫一些擴展包裝函數週圍exp()extended_exp()

#define NegativeNaN log(-1) 

等等!