2016-08-16 30 views
-2

我有從標準::絕對不正確的結果與MSVC和GCC爲什麼標準:: ABS輸出不正確上MSVC2015

#include <cmath> 
#include <iostream> 
#include <complex> 

int main() 
{ 
    std::cerr << std::sqrt((-6.)*(-6.) + 288.*288.) << "\n"; 
    std::cerr << std::abs(std::complex<float>(-6, 288)) << std::endl; 

    return 0L; 
} 

以上代碼生成VC上不同的結果++(MSVS 2015 CE與更新)和GCC 4.9.2

隨着MSVC

288.062 
288.063 

隨着GCC

288.062 
288.062 

現在實際結果是288.062,這在gcc上用std :: abs和std :: sqrt是正確的。但是當使用std :: sqrt和std :: abs可能是msvc2015中的一個bug時,msvc會有不同的結果。

但看着xcomplex的代碼,我不明白_Fabs()的實現。有人能幫我理解這個特定的代碼,並且可以分析代碼如何以這樣的錯誤結束。

+1

請注意,在第一行中,您正在使用雙打。 –

+0

您是否真的認爲所有這些浮點操作都會爲兩個不同的編譯器產生完全相同的結果,因爲浮點數是近似值?如果您使用相同的編譯器得到不同的結果,但改變了一些編譯器選項(如優化或其他設置),我不會感到驚訝。 – PaulMcKenzie

回答

6

「現在實際結果是288.062 [...]」。 - 實際結果是288.06249...,或類似的東西,它不能完全由floatdouble表示。

兩種編譯器實際上返回相同的值,可以通過印刷更多的數字檢查:

double re = -6, im = 288; 
std::cout << "sqrt: " << '\n' 
      << std::setprecision(6) << std::sqrt(re * re + im * im) << '\n' 
      << std::setprecision(30) << std::sqrt(re * re + im * im) << '\n'; 
std::cout << "abs: " << '\n' 
      << std::setprecision(6) << std::abs(std::complex<float>(im, re)) << '\n' 
      << std::setprecision(30) << std::abs(std::complex<float>(im, re)) << '\n'; 

輸出(既VC 19.0和GCC 4.9.3):

sqrt: 
288.062 
288.062493219787313591950805858 
abs: 
288.062 
288.0625 

兩種編譯器實際上返回288.0625std::abs ,但GCC輸出288.62(floor)和VC 288.063(ceil) - 這不是std::abs中的「問題」,而是「問題」輸出格式爲。

這兩種編譯器,因爲使用的是floatstd::abs,而你正在使用doublestd::sqrt返回與std::abs不太近似值。用6.f288.fstd::complex<float>std::complex<double>替代6.288.,您將得到與std::sqrtstd::abs相同的結果。

據我所知,使用std::ostream當標準沒有定義舍入浮點值的一種方式,實際規格來自printf格式轉換%f建議四捨五入的方式(我認爲這是gcc使用「round half to even」的方式)。

+0

^1或更改爲'std :: complex (-6,288)' –

相關問題