为什么 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。
If the argument is less than -0, FE_INVALID is raised and NaN is returned.
... 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
。
相反,此操作 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。
If the argument is less than -0, FE_INVALID is raised and NaN is returned.
... 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
。