2014-09-12 45 views
8

我有一些非常簡單的代碼來處理:如何浮點溢出輸入輸出流

#include <iostream> 
#include <sstream> 
using namespace std; 

int main() 
{ 
    stringstream is("1.0 2.0 1e-500 1e500 12.0"); 
    double d = {17.0, 17.0, 17.0, 17.0, 17.0}; 

    for (int i=0; i < 5; ++i) 
    { 
    if (is >> d[i]) 
    { 
     cout<<"Conversion succeeded"<<endl; 
    } 
    else 
    { 
     cout<<"Conversion failed"<<endl; 
     is.clear(); 
    } 
    } 
    for (int i=0; i < 5; ++i) cout<<d[i]<<endl; 
} 

當我編譯這段代碼G ++ 4.1.2在Redhat 5.10(相同的編譯器)運行它,我得到的輸出:

Conversion succeeded 
Conversion succeeded 
Conversion failed 
Conversion failed 
Conversion succeeded 
1 
2 
0 
17 
17 
12 

當我在Redhat Linux上執行相同的二進制6.5(編譯器4.4.7),我得到

Conversion succeeded 
Conversion succeeded 
Conversion succeeded 
Conversion failed 
Conversion succeeded 
1 
2 
0 
1.79769e+308 
12 

什麼是電子預期行爲?下溢在4.4.7上成功,但在4.1.2上失敗。溢出失敗(但仍然改變值)在4.4.7上,並且在沒有改變4.1.2上的任何內容的情況下失敗。

行爲是未定義的還是簡單地不正確?

+0

好問題。 '>>'是間接的(通過'num_get'),按照'strtold'的規則來定義,對於後者,明確地說未規定下溢是否被視爲錯誤條件。但是,下溢不會被視爲「num_get」的錯誤條件之一。我不確定這是否意味着它沒有指定,或者定義爲成功返回0。 – hvd 2014-09-12 14:52:59

回答

3

根據C++ 11 22.4.2.1.2,轉換失敗的溢出,但不下溢。在溢出的情況下,它應該仍然給出最大的可表示值以及設置failbit

所以你最近的編譯器有正確的現代行爲。

但是,您的古代編譯器早在C++ 11之前就已經存在多年。在較早的標準中,如果scanf會將轉換指定爲給出錯誤;而不是在錯誤的情況下給出價值。轉向C標準,scanf按照strtod,這反過來指定溢出錯誤;但下溢時是否有錯誤是由實現定義的。

所以你的舊編譯器與歷史行爲一致。