避免在 C++ 中部分虚构的表达式使用 NAN

Avoiding NANs for expressions that are partly imaginary in c++

我有一个表达式,其结果是一个实数,但由虚数项组成(相互抵消)。一个比我正在考虑的例子简单得多的例子是,

z = a + 1/[sqrt(a-b) - a] - f[sqrt(a-b)] = a

其中a和b是实数,f是满足上述表达式的某个函数。你不会感到惊讶,在某些情况下,比如对于 b > a(这并不总是发生,但在某些情况下可能发生),上面的表达式 returns nan,因为它的一些术语是虚构的。

有时,仅使用实数就可以算出代数并写出这个并不复杂的表达式。然而,就我而言,代数非常混乱(混乱到连 Matlab 的符号包和 Mathematica 都无法简单地简化)。

我想知道是否有其他方法可以计算出您知道是真实的但部分是虚构的表达式。


PS:对于这个问题并不重要,但有关我正在处理的表达式的更多信息,请参阅another question I previously asked

tl;dr 评论线程:

如果您知道自己正在做的事情会涉及虚数,只需使用 std::complex

如果您坚持要求对某个您知道会包含虚部的事物(例如,sqrt)求一个实数结果,则您无法避免得到 NaN。 它无法给你真正的答案。

在计算结束时,如果 imag(result) 为零(或在合适的 epsilon 范围内),则虚部抵消,得到 real(result).

举个具体的例子:

#include <complex>
#include <iostream>

int main()
{
    std::complex<double> a{-5, 0}; // -5 + 0i
    std::complex<double> b{ 5, 0}; // +5 + 0i
    auto z = b + sqrt(a) - sqrt(a);
    std::cout  << "z = " << real(z) << " + " << imag(z) << "i\n";
}

打印

z = 5 + 0i

用你的新例子

z = a + 1/(sqrt(a-b) - a) - f(sqrt(a-b)) = a

首先将 a 设为 std::complex 类型,然后对分子使用复数 1+0i 会很有用。这是因为重载运算符的解析方式:

using cx = std::complex<double>;

cx f(cx); // whatever this does, it also needs to handle complex inputs

cx foo(cx a, cx b)
{
  return a + cx{1}/(sqrt(a-b) - a) - f(sqrt(a-b));
}
auto