2010-05-05 46 views
10

我在visual studio express中使用C++來生成用於遺傳算法類型程序的隨機表達式樹。如何使用try ... catch捕獲浮點錯誤?

因爲它們是隨機的,所以樹經常產生:除以零,溢出,下溢以及返回「inf」和其他字符串。我可以爲字符串編寫處理程序,但文獻讓我對其他人感到困惑。如果我理解正確,我必須先設置一些標誌?

建議和/或指向一些文獻,將不勝感激。 編輯:雙變量返回的值是1.#INF或-1。#IND。我錯把它們稱爲字符串。

+0

C++並沒有規定任何這些行動應該拋出一個異常拋出來FPU異常。他們導致未定義的行爲。 (可能會崩潰,或者拋出異常,或者什麼也不做,......) – GManNickG 2010-05-05 00:39:12

+1

但是C99和POSIX確實指定了這些東西,並提供了一個數字異常接口。然而,如果彼得能夠控制實際的數字,如果他得到的是字符串而不是FP的無窮大,那麼有點不清楚。 – Potatoswatter 2010-05-05 01:59:00

回答

6

你確定你想趕上他們,而不是僅僅忽略它們?假設你只是想忽略他們:

看到這個: http://msdn.microsoft.com/en-us/library/c9676k6h.aspx

對於_MCW_EM面膜,清除屏蔽器設置例外,這使得硬件異常;設置掩碼會隱藏異常。

所以你會想要做這樣的事情:

#include <float.h> 
#pragma fenv_access (on) 

void main() 
{ 
    unsigned int fp_control_word; 
    unsigned int new_fp_control_word; 

    _controlfp_s(&fp_control_word, 0, 0); 

    // Make the new fp env same as the old one, 
    // except for the changes we're going to make 
    new_fp_control_word = fp_control_word | _EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW | _EM_INEXACT; 
    //Update the control word with our changes 
    _controlfp_s(&fp_control_word, new_fp_control_word, _MCW_EM) 


} 

這裏的某些混亂的可能是在使用這個詞「異常」的。在C++中,通常是指語言內置的異常處理系統。浮點異常是完全不同的野獸。標準FPU需要支持的例外均在IEEE-754中定義。這些發生在浮點單元內部,這取決於如何設置浮點單元的控制標誌可以做不同的事情。通常發生以下兩種情況之一: 1)忽略該異常,並且FPU設置一個標誌,指示其狀態寄存器中發生錯誤。 2)FPU不會忽略異常,所以會產生一箇中斷,並且會爲調用浮點錯誤而設置任何中斷處理程序。通常這會對你造成不良影響,例如導致你在調試器中的那行代碼中斷或生成一個核心文件。

你可以找到更多的IEE-754在這裏:http://www.openwatcom.org/ftp/devel/docs/ieee-754.pdf

一些額外的浮點引用: http://docs.sun.com/source/806-3568/ncg_goldberg.html http://floating-point-gui.de/

+1

假設代碼在x86處理器上運行... – dthorpe 2010-05-05 00:45:45

+1

dthorpe:實際上,我沒有假設它在x86處理器上運行。 MSDN文檔明確指出_controlfp_s是新的「獨立於平臺」的新方法。我懷疑,通過平臺獨立,他​​們指的是CPU類型,顯然不是所有的x86操作系統都有這個功能 - 只要他在Windows平臺上這樣做,他應該沒問題。 – George 2010-05-05 01:03:43

+2

另外請注意,我已經看到了圖書館正在對浮點控制字的設置進行交戰,每個控制字都強加於它的偏好。幾乎和打印機驅動程序在一個程序的feed中改變語言環境一樣糟糕...... – 2010-05-05 10:06:59

-1

從來沒有嘗試過,但零假設鴻溝拋出一個異常,你可以只換行代碼一個try/catch這樣的:

嘗試 {// 潛在的被零除... } 趕上(...) { // ...捕獲所有異常 }

+0

這是錯誤的,因爲C++運行時環境在這裏不會幫助你。除了程序員專門要求的東西外,它不會拋出任何異常。 – wilhelmtell 2010-05-05 00:40:39

1

C++運行時環境不會幫你絲毫這裏。你必須自己執行這些檢查,明確地在你的代碼中。除非你正在調用的函數正在執行這些檢查 - 在這種情況下,這取決於它們在出現錯誤時的行爲方式。

讓我解釋一下:

double divide(double a, double b) { 
    return a/b; // undefined if b is zero 
} 

應在事實上

double divide(double a, double b) { 
    if(b == 0) { 
     // throw, return, flag, ... you choose how to signal the error 
    } 
    return a/b; // b can't possibly be zero here 
} 

如果上失敗的代碼除以零,這樣是不是你的,那麼你就必須挖掘更深入地發現它在出現錯誤威脅時的作用。它扔?設置一個標誌?詢問作者和/或閱讀來源。

下面是一個例外的例子:

struct bad_value : public std::exception { }; 

double divide(double a, double b) { 
    if(b == 0) throw bad_value("Division by zero in divide()"); 
    return a/b; // b can't possibly be zero here 
} 

// elsewhere (possibly in a parallel universe) ... 

    try { 
     double r1 = divide(5,4); 
     double r2 = divide(5,0); 
    } catch(bad_value e) { 
     // ... 
    } 
+0

謝謝。看起來我必須執行我自己的'扔'。 – 2010-05-05 10:13:51

8

http://msdn.microsoft.com/en-us/library/aa289157%28v=vs.71%29.aspx#floapoint_topic8
似乎有可能拋出C++在MSVC異常

創建例外類:

class float_exception : public std::exception {}; 
class fe_denormal_operand : public float_exception {}; 
class fe_divide_by_zero : public float_exception {}; 
class fe_inexact_result : public float_exception {}; 
class fe_invalid_operation : public float_exception {}; 
class fe_overflow : public float_exception {}; 
class fe_stack_check : public float_exception {}; 
class fe_underflow : public float_exception {}; 

地圖C++使用結構化異常處理程序

void se_fe_trans_func(unsigned int u, EXCEPTION_POINTERS* pExp) 
{ 
    switch (u) 
    { 
    case STATUS_FLOAT_DENORMAL_OPERAND: throw fe_denormal_operand(); 
    case STATUS_FLOAT_DIVIDE_BY_ZERO:  throw fe_divide_by_zero(); 
    etc... 
    }; 
} 
. . . 
_set_se_translator(se_fe_trans_func); 

然後,您可以使用嘗試捕捉

try 
{ 
    floating-point code that might throw divide-by-zero 
    or other floating-point exception 
} 
catch(fe_divide_by_zero) 
{ 
    cout << "fe_divide_by_zero exception detected" << endl; 
} 
catch(float_exception) 
{ 
    cout << "float_exception exception detected" << endl; 
} 
+2

這應該是認可的答案:它對應於原始問題(接受的答案基本上說「你不應該打擾」,第二個說「你不行」(這是不正確的)。 – Deimos 2014-10-07 13:36:29