0

以前、C#.Net Mandelbrot セットに関する質問を投稿しましたが、これは有益な回答でしたが、この Mandelbrot セットに戻って、(虚数と実数) 座標を定義する double 変数に構造体を実装する必要がありました。

構造体を初めて使用し、少し錆びている人として、私が間違っていることと、上記のコードを見るだけで改善する方法について少しアドバイスをお願いします。わずかに最適化できると確信しています。 . これは構造体を利用する正しい方法ですか? そうでない場合、代替手段または最良の手法は何ですか? ありがとう。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace wmcMandelbrot
{
struct doubleVar
{

    public double realCoord, imagCoord;
    public double realTemp, imagTemp, realTemp2, arg;
    public double newIcoord, newIcoord1, newIcoord2;
    public double rCoord, rCoord1, rCoord2;
 }


class Program
{
    static void Main(string[] args)
    {

        doubleVar doubleNum;
        int iterations;

        Console.WriteLine("Enter first imaginary coord: ");
        doubleNum.newIcoord = Convert.ToDouble(Console.ReadLine());

        Console.WriteLine("Enter second imaginary coord: ");
        doubleNum.newIcoord1 = Convert.ToDouble(Console.ReadLine());

        Console.WriteLine("Enter third imaginary coord: ");
        doubleNum.newIcoord2 = Convert.ToDouble(Console.ReadLine());

        Console.WriteLine("Enter first real coord: ");
        doubleNum.rCoord = Convert.ToDouble(Console.ReadLine());

        Console.WriteLine("Enter second real coord: ");
        doubleNum.rCoord1 = Convert.ToDouble(Console.ReadLine());

        Console.WriteLine("Enter third real coord: ");
        doubleNum.rCoord2 = Convert.ToDouble(Console.ReadLine());

        for (doubleNum.imagCoord = doubleNum.newIcoord; doubleNum.imagCoord >= -doubleNum.newIcoord1; doubleNum.imagCoord -= doubleNum.newIcoord2)
        {
            for (doubleNum.realCoord = -doubleNum.rCoord; doubleNum.realCoord <= doubleNum.rCoord1; doubleNum.realCoord += doubleNum.rCoord2)
            {
                iterations = 0;
                doubleNum.realTemp = doubleNum.realCoord;
                doubleNum.imagTemp = doubleNum.imagCoord;
                doubleNum.arg = (doubleNum.realCoord * doubleNum.realCoord) + (doubleNum.imagCoord * doubleNum.imagCoord);
                while ((doubleNum.arg < 4) && (iterations < 40))
                {
                    doubleNum.realTemp2 = (doubleNum.realTemp * doubleNum.realTemp) - (doubleNum.imagTemp * doubleNum.imagTemp) - doubleNum.realCoord;
                    doubleNum.imagTemp = (2 * doubleNum.realTemp * doubleNum.imagTemp) - doubleNum.imagCoord;
                    doubleNum.realTemp = doubleNum.realTemp2;
                    doubleNum.arg = (doubleNum.realTemp * doubleNum.realTemp) + (doubleNum.imagTemp * doubleNum.imagTemp);
                    iterations += 1;
                }
                switch (iterations % 4)
                {
                    case 0:
                        Console.Write(".");
                        break;
                    case 1:
                        Console.Write("o");
                        break;
                    case 2:
                        Console.Write("O");
                        break;
                    case 3:
                        Console.Write("@");
                        break;
                }
            }
            Console.Write("\n");
        }
        Console.ReadKey();




    }
  }
}
4

2 に答える 2

3

各複素数を表すには構造体を使用する必要があると思います。その構造体には、これらの複素数を加算、減算、乗算する関数を含めることができます。

例えば。

struct Complex
{
    public double real;
    public double imag;

    public Complex(double r, double i)
    {
        real = r;
        imag = i;
    }

    public Complex add(Complex operand)
    {
        return new Complex(real + operand.real, imag + operand.imag);
    }

    public Complex multiply(Complex operand)
    {
        return new Complex(real * operand.real - imag * operand.imag, real * operand.imag + operand.real * imag);
    }
}

次に、構造体を使用するには、次のようなことができます

Complex c = new Complex( ...coordinate goes here... );
Complex z = new Complex(0,0);

// z -> z^2 + c
Complex result = z.multiply(z).add(c);

また、複素数構造体に「sq」(数値を 2 乗)、「pow」(特定の累乗)、または「arg」(上記のコード) を追加することもできます。空は限界です!これらの関数は別の複素数を返す必要がないことに注意してください。たとえば、"arg" は double を返します。

また、常に 2 つの複素数 (マップ ポイントと z 値) をグループ化する場合は、2 つの複素数を保持する構造体を作成できます。

struct MapPoint
{
    Complex c;
    Complex z;
}

等々。私にとって、論理的に分割できないものや、常にグループとして処理されるものを構造体にグループ化することは理にかなっています。

于 2012-09-07T01:00:59.353 に答える
1

座標 (読み取り部分と虚数部分) を定義するために必要な値のみを格納し、一時的な値は格納しないことは理にかなっています。また、計算された値は、次のようにプロパティにすることもできます。

public struct MapPoint
{
    public double realCoord, imagCoord;
    public double realConst, imagConst;

    public MapPoint(double realConst, double imagConst)
        : this(realConst, imagConst, realConst, imagConst) { }

    public MapPoint(double realCoord, double imagCoord, double realConst, double imagConst)
    {
        this.realCoord = realCoord;
        this.imagCoord = imagCoord;
        this.realConst = realConst;
        this.imagConst = imagConst;
    }
    public double Argument // calculated property
    {
        get { return realCoord * realCoord + imagCoord * imagCoord; }
    }

    public MapPoint Iterate()
    {
        // Do the z = z^2+c thing

        return new MapPoint(
            realCoord * realCoord - imagCoord * imagCoord + realConst,
            2 * realCoord * imagCoord + realConst,
            realConst, imagConst);
    }
}

この構造を次のように使用します。

void Main() {
    for( double y=...
      for( double x=...

        int iterations = 0;
        MapPoint point = new MapPoint(x, y);

        while (iterations < 40 || point.Argument < 4.0)
        {
            point = point.Iterate();
            iterations++;
        }

        switch (iterations % 4)
        {
            //...
        }
    ...
}

これの鍵は、情報が保存されている場所の近くの構造内ですべての計算が行われることです。このようにして、計算ブロックを再度書き直す必要なく、最小限の労力で構造体を他の場所で再利用できます。また、一時的な値は不要なときに破棄され、重要な値の隣に保存されません。

ここここで構造を読んでから、上記のコードを自分のものとして書き直すことを約束してください。

于 2012-09-07T00:32:15.887 に答える