4

C++11 で複素数の実数値または imag 値への参照を返す関数を探しています。C++03 では、次のように言えます。

complex<double> C; cin >> C.real();

しかし、C.real() が参照ではなく値を返すため、C++11 ではコンパイル エラーが発生します。

私はこれを書くことができることを知りました:

double t; cin >> t; C.real(t);

しかし、それは簡単ではありません。たとえば、c の実部を 2 倍して 1 倍にしたい場合は、次のように言う必要があります。

C.real(2*C.real() + 1);

それはきれいではありません。

それを行う他の[クリーンな]方法はありますか?

4

6 に答える 6

4

否定的で申し訳ありませんが、あなたの質問は間違った前提から始まります。2011 規格に関してstd::complexは下位互換性があります。フォームのコード

complex<double> C; cin >> C.real();

有効な C++ではありませんでした。2003年の標準はメンバー関数のみを提供します

T std::complext<T>::real() const;

だがしかし

const T& std::complext<T>::real() const;  // non-standard
T& std::complext<T>::real();              // non-standard

一部の実装 (gcc 4.3 に同梱されているものなど) では、代わりにこれら 2 つが実装されている場合があります。

さて、あなたの質問に答えます。明らかに、最もクリーンな方法は、標準の意図に従うことです。2011 規格では、次のセッターが追加されています

void std::complex<T>::real(T);
void std::complex<T>::imag(T);

したがって、これらを使用して、実部または虚部を個別に設定するだけです。

T&ただし、などの を取る関数では使用できませんoperator>>。そのためには、次のような厄介なトリックを行う必要があります

template<typename T>
inline T& get_real(std::complex<T>&z) { return reinterpret_cast<T(&)[2]>(z)[0]; }

template<typename T>
inline T& get_imag(std::complex<T>&z) { return reinterpret_cast<T(&)[2]>(z)[1]; }

std::complex<double> z;
cin >> get_real(z) >> get_imag(z);

実際、bames53 のコメントで指摘されているように、標準ではstd::complex、これが常に機能するようにレイアウトされることが保証されています。

于 2013-10-04T09:14:31.263 に答える
3

C++11 で許可されるようになりました

double& re(std::complex<double>& c)
{
    return reinterpret_cast<double (&)[2]>(c)[0];
}

double& im(std::complex<double>& c)
{
    return reinterpret_cast<double (&)[2]>(c)[1];
}

const double& re(const std::complex<double>& c)
{
    return reinterpret_cast<const double (&)[2]>(c)[0];
}

const double& im(const std::complex<double>& c)
{
    return reinterpret_cast<const double (&)[2]>(c)[1];
}

使用法:

std::complex<double> a;
std::cin >> re(a);

関連引用§26.4:

さらに、 a が 型の式でcv std::complex<T>*あり、その式a[i]が整数式 に対して明確に定義されている場合i、 —reinterpret_cast<cv T*>(a)[2*i]は の実部を指定しa[i]、 —reinterpret_cast<cv T*>(a)[2*i+1]は の虚部を指定しa[i]ます。

于 2013-10-04T10:49:13.923 に答える
2

実数部分を操作したい場合は、double または float を直接使用できます。虚数部を操作したい場合は、一意の複素数を取得して、必要なstd::complex<double> I(0,1)値を掛けることができます。

たとえば、次のように書く代わりに、次のように書くC.real(2*C.real() + 1);ことができます。C += C.real() + 1;

次に、数式で double と complex を混在させると、コンパイラは正しい変換を使用します。例を参照してください。

#include <iostream>
#include <complex>

int main(int argc, char* argv[])
{
    // Let the user enter a Real number
    double c;
    std::cin >> c;

    // Explicitly convert to a complex
    std::complex<double> C = 2*c + 1;
    std::cout << C << std::endl;

    // Creates a pure imaginary complex number I
    std::complex<double> I(0,1);

    // Mix together complex and real numbers in the
    // same expression
    C = C + c*I;
    std::cout << C << std::endl;


    // Setup a specific value and compare how to achieve
    // C.real = 2*C.real + 1
    C = 1. + 2.*I;
    C.real(2*C.real()+1);
    std::complex<double> D = 1. + 2.*I;
    D += D.real() + 1;
    std::cout << "C=" << C << "\tD=" << D << std::endl;

    return 0;
}

出力:

$ ./main.exe
1
(3,0)
(3,1)
C=(3,2) D=(3,2)

$ ./main.exe
2
(5,0)
(5,2)
C=(3,2) D=(3,2)

参照を介して直接影響を与える場合と比較して、このメソッドの効率が失われることが心配な場合は、生成されたアセンブリ コードを確認できます。私のコンピューターではg++-O3すべてがインライン化されています。

于 2013-10-04T08:14:43.303 に答える
1

私が知っていることではありません。

それが重要な場合は、ヘルパーを作成できます。

class ModifyReal
{
   double d;
   complex<double> & c;
public:
   ModifyReal(complex<double> & c_) : c(c_), d(numeric_limits<double>::quiet_NaN()) 
   {}
   operator double &() { return d; }
   ~ModifyReal() { c.real(d); }
};


cin >> ModifyReal(C);

ただし、非常にやむを得ない理由がない限り、これを使用することはお勧めしません。(「好きじゃない」では説得力が足りない。)

コードにこのような多くの異なるクラスがあると読みやすさが損なわれる可能性があると思いますが、いくつかの専用インスタンスで使用する場合は問題ありません。エラー処理が微妙に難しくなる可能性があります (たとえば、cin は無効な入力をスローしないため、C は変更されないのではなく、nan が割り当てられます)。


「きれい」とはどういう意味ですか?いいえ、言わないでください-考えてみてください。

于 2013-10-04T07:54:17.080 に答える
-2

Steve Jessop にインスパイアされた、まさにC += (C + C.conj())/2 + 1;.

複雑な数学では、実数部と虚数部を完全に独立したコンポーネントとして実際に扱うことはできないことに注意してください。これは、位相と大きさを完全に独立したコンポーネントとして扱うよりも正気です。複素数の加算は実数部と虚数部で別々に行われますが、乗算は位相と大きさの部分で別々に行われます。

std::complexあなたの例は複雑な乗算ではないため、そのような乗算をサポートしていないのは理にかなっています。

于 2013-10-04T10:00:31.377 に答える