2016-08-16 6 views
-2

に間違っている:: MSVCとGCC理由はstd :: ABS出力は、私がSTDから不正な結果が生じています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 GCC

でMSVC

288.062 
288.063 

288.062 
288.062 

実際の結果はgdでstd :: absとstd :: sqrtで正しい288.062です。しかし、msvcはstd :: sqrtとstd :: absを使用した場合、msvc2015のバグとなる可能性があります。

xcomplexのコードを見ると、私は_Fabs()の実装を理解していません。誰かが私にこの特定のコードとそのコードがどのようにこのようなバグで終わったかの可能な分析を理解する助けになるかもしれません。

+1

最初の行では2倍を使用しています。 –

+0

浮動小数点は近似値であるため、この浮動小数点操作のすべてが2つの異なるコンパイラに対してまったく同じ結果をもたらすと本当に思いましたか?私はあなたが同じコンパイラを使用することとは異なる結果を得たが、いくつかのコンパイラオプション(最適化やその他の設定など)を変更しても驚くことはありません。 – PaulMcKenzie

答えて

6

"実際の結果は288.062 [...]です。" - 実際の結果は288.06249...などです。正確にはfloatまたはdoubleで表すことはできません。

どちらのコンパイラは、実際にあなたがより多くの数字を印刷して確認することができ、同じ値を返します(VC 19.0とGCC 4.9.3の両方で)

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'; 

出力:

sqrt: 
288.062 
288.062493219787313591950805858 
abs: 
288.062 
288.0625 

どちらのコンパイラ、実際にstd::abs のGCC出力288.62(フロア)とVC 288.063(ceil)の288.0625を返します。これはstd::absの「問題」ではなく「問題」です。出力のフォーマットはです。あなたはstd::sqrtdoubleを使用している間、あなたはstd::absためfloatを使用しているため

両方のコンパイラはstd::absとあまり近似値を返します。 6.288.6.f288.fまたはstd::complex<float>と置き換えてstd::complex<double>と置き換えますと、std::sqrtstd::absと同じ結果になります。 std::ostreamを使用した場合

私の知る限りでは、標準の浮動小数点値を丸めの方法を定義していない、実際の仕様は唯一(丸めの方法ををお勧めしますprintfフォーマット変換%fから来ていますこれは、gccのラウンドを「偶数ラウンド」にする方法です)。

+0

^1または 'std :: complex (-6,288)'に変更してください –

関連する問題