为什么在MSVC2015上std :: abs输出不正确

rkm*_*rkm -2 c++ visual-c++

我在使用MSVC和GCC的std :: abs时得到的结果不正确

#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;
}
Run Code Online (Sandbox Code Playgroud)

上面的代码在VC++(带有更新的MSVS 2015 CE)和gcc 4.9.2上产生了不同的结果

使用MSVC

288.062
288.063
Run Code Online (Sandbox Code Playgroud)

与GCC

288.062
288.062
Run Code Online (Sandbox Code Playgroud)

现在实际结果是288.062,这对于gcc与std :: abs和std :: sqrt是正确的.但是当使用std :: sqrt和std :: abs时,msvc有不同的结果,这可能是msvc2015中的一个错误.

但是看看xcomplex的代码,我不明白_Fabs()的实现.有人可以帮助我理解这个特定的代码,并可能分析代码如何以这样的错误结束.

Hol*_*olt 6

"现在实际结果是288.062 [...]." - 实际结果是288.06249...,或类似的东西,不能用a float或a表示double.

两个编译器实际上都返回相同的值,您可以通过打印更多数字来检查:

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';
Run Code Online (Sandbox Code Playgroud)

输出(VC 19.0和GCC 4.9.3):

sqrt: 
288.062
288.062493219787313591950805858
abs:  
288.062
288.0625
Run Code Online (Sandbox Code Playgroud)

这两种编译器实际上返回288.0625std::abs1,但GCC输出288.62(楼)和VC 288.063(小区) -这是不是一个"问题" std::abs,但在输出方式的"问题"被格式化2.

1个这两种编译器返回一个不太近似值std::abs,因为你正在使用floatstd::abs,而你正在使用doublestd::sqrt.更换6.288.通过6.f288.fstd::complex<float>通过std::complex<double>,你会得到相同的结果与std::sqrtstd::abs.

2据我所知,标准没有定义一种在使用时舍入浮点值的方法std::ostream,实际的规格来自printf格式转换%f,它只推荐一种舍入方式(我认为,这是gcc使用圆形的方式)一半甚至").