C# Kompleksiluku luokka

gummikana 10.05.04 20:14

Esittelee miten C#:ssä tehdään operaattorien overloadaus ja on myös ihan toimiva kompleksiluku luokka

 Tekstiversio  Arvo: 4 (4 ääntä)  Äänestä: +  -
////////////////////////////////////////////////////////////////////////
// CComplex luokka.
//
// 10.5.2004 Petri Purho    pete@markkupurho.fi
//
//
// Kompleksiluku luokka joka myös esittelee miten C#:ssä tehdään
// operaattorien overloadaus.
//
// Koodi löytynee myös täältä:
//
// http://koti.mbnet.fi/kumikana/soodaus/cs/CComplex/
//
////////////////////////////////////////////////////////////////////////
using System;

namespace Matikka
{
    // Kompleksiluku luokka...
    public class CComplex
    {
        /////////////////////////////////////////////////////////////////
        public CComplex()
        {
            myReal = 0;
            myImg = 0;
        }

        public CComplex( double real, double img )
        {
            myReal = real;
            myImg = img;
        }
       
        // Toisin kuin C++:ssa  niin C#:ssä ei konstruktoreista tehdä
        // sijoitus-operaattoreita. Itseasiassa sijoitus-operaattoreita
        // ( operator= ) ei C#:ssä ole samaan tyyliin kuin C++:ssa. Jos jotain
        // kopioidaan ( esim. CComplex x = u; ) niin tehdä aina bittikopio.
        //
        // Implisiittisiä kopioita voi kyllä tehdä seuraavaan tyyliin:
        /*
            public static implicit operator CComplex( double s )
            {
                return new CComplex( s, s );
            }
        */

        // kyseistä funktiota kutsuttaisiin esim seuraavassa skenaariossa:
        /*
            CComplex z = 1.5;
         */

        // Mutta koska kompleksilukuihin ei suoranaisesti sovi implisiittiset
        // konvertiot, niin olen sen jättänyt pois, mutta jos jotain kiinnostaa
        // niin siellä se on.
        //
        // Konstruktorin voi tehdä omasta tyypistään, mutta se on vähän turhaa
        // koska sitä kutsuttaisiin vain seuraavanlaisessa skenaariossa:
        /*
            CComplex z = new CComplex( 10, 10 );
            CComplex u = new CComplex( z );     
        */


        public CComplex( CComplex other )
        {
            Console.WriteLine( "jees box" );
            myReal = other.real;
            myImg = other.img;
        }
       
        //--------------------------------------------------------------
        // operaattori-overloadausta....
        // =============================================================

        // Näitä käytetään esim seuraavassa tapauksessa:
        /*
          CComplex z = new CComplex( 3, 6 );
          CComplex u = new CComplex( -9, 3 );
         
          CComplex sum = z + u;
         
          // Tai epäsuorasti näin...
          z -= u;
         
        */

        public static CComplex operator+ ( CComplex one, CComplex two )
        {
            CComplex sum;

            sum = new CComplex( one.real + two.real, one.img + two.img );

            return sum;
        }

        public static CComplex operator- ( CComplex one, CComplex two )
        {
            CComplex sum;

            sum = new CComplex( one.real - two.real, one.img - two.img );

            return sum;
        }


        // operator+ ( CComplex other ) ei oikeastaan tee juuri mitään...
        // mutta operator- ( CComplex other ) kääntää luvun negatiiviseksi
        // Näitä taas käytetään esim seuraavassa tapauksessa:
        /*
            CComplex z = new CComplex( 4, 5 );
            z = -z;
        */

        public static CComplex operator+ ( CComplex other )
        {
            return other;
        }

        public static CComplex operator- ( CComplex other )
        {
            CComplex sum;
           
            sum = new CComplex( - other.real, - other.img );

            return sum;
        }

       
        // Näitä käytetään esim seuraavissa tapauksissa:
        /*
            CComplex z = new CComplex( 4, 6 );
            CComplex u = new CComplex( -9, 2 );
           
            CComplex sum = z * u;
           
            z /= u;
         */

        public static CComplex operator* ( CComplex one, CComplex two )
        {
            CComplex sum;
           
            double real;
            double img;

            real = ( ( one.real * two.real ) - ( one.img * two.img ) );
            img = ( ( one.real * two.img ) + ( one.img * two.real ) );

            sum = new CComplex( real, img );

            return sum;
        }

        public static CComplex operator/ ( CComplex one, CComplex two )
        {
            CComplex sum;

            double real;
            double img;

            real = ( one.real * two.real + one.img * two.img ) / ( Math.Pow( two.real, 2 ) + Math.Pow( two.img, 2 ) );
            img = ( one.img * two.real - one.real * two.img ) / ( Math.Pow( two.real, 2 ) + Math.Pow( two.img, 2 ) );

            sum = new CComplex( real, img );

            return sum;
        }


        // Vertailu operaattorit...
        // Nämä, kuten muutkin bittioperaattorit ( <, > <=, => ) pitää
        // aina kirjoittaa pareittaan. Eli jos teet overloadaad <
        // operaattorin, täytyy sinun myös kirjoittaa koodi > operaattorille.
        //
        // Jos overloadaad vertailu operaattorit pitää sinun overridettaa
        // int GetHashCode() ja bool Equals( object o ) funktiot.
        //
        // Nämä kyseiset funktiot on overridetettu alempana.
        //
        // Vertailu operaattoreita käytetään esim seuraavassa tapauksessa:
        /*
            CComplex z = new CComplex( 1, 1 );
            CComplex u = new CComplex( 1, 0 );
           
            if ( z == u ) Console.WriteLine( "Ovat yhtäsuuret" );
         */


        public static bool operator==( CComplex one, CComplex two )
        {
            return ( one.real == two.real && one.img == two.img );
        }

        public static bool operator!=( CComplex one, CComplex two )
        {
            return ( one.real != two.real || one.img != two.img );
        }


        //--------------------------------------------------------------

        // Nämä kaksi Equals ja GetHashCode pitää overridettaa, jotta
        // vertailu operaattoreita voisi käyttää...
        public override bool Equals(object o)
        {
            return this==(CComplex)o;
        }

        public override int GetHashCode()
        {
            return (int)( myReal + myImg );
        }

       
        // Tätä metodia kutsutaan kun olio printataan consoliin.
        // esim
        /*
           CComplex z = new CComplex( 1, 0 );
           Console.WriteLine( z );
         */

         
        public override string ToString()
        {
            return "" + real + ", " + img + "i";
        }


        //--------------------------------------------------------------

        // ainut varsinainen normaali metodi...
        public bool IsZero()
        {
            return ( myReal == 0 && myImg == 0 );
        }


        //--------------------------------------------------------------
       
        // Tässä on esimerkki C#:än tavasta käsitellä julkisia muuttujia.
        // C++:ssa koodattiin hyviä GetReal() ja SetReal( double real )
        // funktioita käsittelemään tämä sama asia. C#:ssa homma hoidetaan
        // puoli automaattisesti. btw. value on sitten varattu sana, jos se
        // pistää ihmetyttämään.
        //
        // Esimerkki käytöstä:
        /*
            CComplex z = new CComplex( 1, 0 );
            z.real = z.img;
        */

        public double real
        {
            get{ return myReal; }
            set{ myReal = value; }
        }

        public double img
        {
            get{ return myImg; }
            set{ myImg = value; }
        }

        // Tämä antaa kompleksiluvun pituuden ja tällä voi määrittää
        // kompleksiluvulle jonkun pituuden.
        // Näppärä vaikka eksponenttimuotoisen esityksen tekemiseen.
        public double r
        {
            get
            {
                return ( Math.Sqrt( ( Math.Pow( myReal, 2 ) + Math.Pow( myImg, 2 ) ) ) );
            }

            set
            {
                double ilength = value * ( 1 / this.r );
                myReal *= ilength;
                myImg *= ilength;
            }

        }

        // Tämä taas antaa ja antaa muuttaa kompeksiluvun vaihekulmaa
        // imaginäriakselin suhteen.
        // Näppärä eksponenttimuotoisen esityksen tekemiseen.
        // Kulmat muuten ovat sitten radeaaneja, ettei tarvi ihmetellä.
        public double arg
        {
            get
            {
                double real = ( Math.Acos( myReal / this.r ) );
                double img  = ( Math.Asin( myImg / this.r ) );
               
                if ( real == img ) return real;
               
                if ( real < 0 ) return real;
                if ( img < 0 ) return img;
               
                return real;
            }

            set
            {
                double r  = this.r;
                myReal = Math.Cos( value ) * r;
                myImg = Math.Sin( value ) * r;
               
            }
        }
       
        //--------------------------------------------------------------
        //
        // Luokan private muuttujat...

        private double myReal;
        private double myImg;
       
        /////////////////////////////////////////////////////////////////


    }


    // Esimerkki ohjelma...
    class CMain
    {
        static void Main(string[] args)
        {
            CComplex z = new CComplex( 1, 1 );
           
            z.r = Math.Sqrt( 13 );
            z.arg = -0.588;
            Console.WriteLine( z );             
        }
    }
}

Anylo 21:26 11.5.04 
Esittelee hyvin operaattorien toimintaa c#:ssa.