为什么 pow(sqrt(-1), 2) return -1 没有?

Why doesn't pow(sqrt(-1), 2) return -1?

相反,此操作 returns -1.IND,因为 sqrt(-1) returns -1.IND。 C++ reference 中提到的域错误是否表示负值的此 sqrt returns 不保留这实际上是 i 的信息?

是否有某种方法可以对所有负数执行此操作,使其 return 成为正确的值,即 pow(sqrt(-36), 2) 将 return -36?

std::sqrt is defined 到 return 域错误上的实现定义错误。在这种情况下 (arg := -1) < -0 是域错误。

std::pow is also defined 到 return 域错误的实现定义错误。

所以接收 -1.Ind 是一个合理的解决方案。

正如 Mystical 指出的那样,您需要一个复数库。

因为您正在调用函数double sqrt(double),而double return 值只能存储实数、无穷大(带符号)或NaN。 i.

没有代表

如果要存储复数,请使用std::complex

来自 this sqrt reference page

If the argument is less than -0, FE_INVALID is raised and NaN is returned.

然后从this pow reference page

... if any argument is NaN, NaN is returned

所以你根本不能用 pow(sqrt(x), y) 来表示任何负数的实数 x

您可以使用 std::complex 来实现您的目标,如下所示:

#include <complex>
#include <iostream>

int main() {
  const std::complex<double> result = 
    std::pow(std::sqrt(std::complex<double>(-36,0)), 2);
  std::cout << result << std::endl;
  std::cout << "Real part = " << result.real() << std::endl;
}

输出:

(-36,0)
Real part = -36

注意这里用的是std::sqrt(std::complex)


您遇到的行为背后的原因是 sqrt 的签名,即:

double sqrt (double x);

float sqrt (float x);

long double sqrt (long double x);

double sqrt (T x); // additional overloads for integral types

这意味着无论使用哪个原型,你都不会得到比 nan (或 +-inf)更好的东西,因为 return 类型不能支持虚部.这就是 std::complex 存在的原因。

因此,sqrt(-1) 可能会被 nan 替换,pow() 无法处理,因此 -1 保持不变,因为指数。结果,调用 sqrt() 后信息已经丢失,pow() 对此无能为力。

如果你可以使用 C++14,你可以使用复杂的文字运算符:#include

<complex>
#include <iostream>

int
main()
{
  using namespace std::literals::complex_literals;
  auto z = std::pow(std::sqrt(-36.0 + 0.0i), 2.0);
  std::cout << z << '\n';
}

运行 我得到:

ed@bad-horse:~$ ./cpow 
(-36,4.40873e-15)

我知道最近 gcc and clang support this. It looks like VS2015 也是。

这实际上是 post-C++14 的补充,但它仍然在 std 命名空间中,而不是 experimental