Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen der Seite angezeigt.

Link zu der Vergleichsansicht

Beide Seiten, vorherige Überarbeitung Vorherige Überarbeitung
Nächste Überarbeitung
Vorherige Überarbeitung
ef_informatik:csharp_oop [2022-03-29 10:31] – [Teil II: Eigenschaften, getter & setter] scaef_informatik:csharp_oop [2022-04-25 19:48] (aktuell) – [Teil IX: Aufgaben] sca
Zeile 39: Zeile 39:
       1. `Magnitude` gibt Länge des Vektors an       1. `Magnitude` gibt Länge des Vektors an
       1. `UnitVector` gibt den zugehörigen Einheitsvektor (wieder ein Vektor!!!) an. Erinnerung: Einheitsvektor zeigt in gleiche Richtung, hat aber Länge $1$.       1. `UnitVector` gibt den zugehörigen Einheitsvektor (wieder ein Vektor!!!) an. Erinnerung: Einheitsvektor zeigt in gleiche Richtung, hat aber Länge $1$.
-      1. `IsZeroVector` gibt `true` (`false`) zurück, wenn Vektor (nicht) ein Nullvektor ist. Achtung: Doubles sind auf etwa $16$ Stellen genau, d.h. sehr kleine Zahlen $<10^{-15}$ sollte man auch als $0$ interpretieren. Definiere dazu eine private Eigenschaft (z.B. `accuracy`) die die Genauigkeit festlegt.+      1. `IsZeroVector` gibt `true` (`false`) zurück, wenn Vektor (nicht) ein Nullvektor ist. Achtung: Doubles sind auf etwa $16$ Stellen genau, d.h. sehr kleine Zahlen $<10^{-15}$ sollte man auch als $0$ interpretieren. Definiere dazu ein private Feld (z.B. `_accuracy`, Underline weil private) die die Genauigkeit festlegt.
       1. `IsUnitVector` gibt `true` (`false`) zurück, wenn Vektor (nicht) ein Einheitsvektor ist. Beachte wieder, dass doubles ungenau sind.       1. `IsUnitVector` gibt `true` (`false`) zurück, wenn Vektor (nicht) ein Einheitsvektor ist. Beachte wieder, dass doubles ungenau sind.
  
Zeile 72: Zeile 72:
 </code> </code>
  
 +   1. **Überlade** nun den **Konstruktor**: Einmal soll diesem nur das Double-Array übergeben werden. Einmal soll zusätzlich ein Wert für die Genauigkeit übergeben werden.
 +   1. Die Genauigkeit soll auch im Nachhinein angepasst werden können, dazu muss diese aber public gemacht werden. Wir wollen aber eine Obergrenze setzen, z.B. soll für die Genauigkeit kein Wert $> 10^{-5}$ (oder was auch immer) gesetzt werden können. Dazu gehen wir wie folgt vor: Wir haben ein privates Feld `_accuracy` und eine public Eigenschaft `Accuracy`. Über dessen **getter/setter** wird der Wert von `_accuracy` gesetzt, wobei sichergestellt wird, dass ein erlaubter Wert gesetzt wird (Stichword: setter!). Siehe z.B. hier für mehr Infos dazu: https://codeasy.net/lesson/properties
 +   1. In Realität benötigt man meist 2D- und 3D-Vektoren. Daher macht es Sinn, für diese Fälle weitere Überladungen des Konstruktors zu machen: `Vecor(3,-42)` und `Vector(3,-42,7)` soll dann einen entsprechenden 2D- resp. 3D-Vektor erzeugen. Die Genauigkeit wird dabei jeweils auf den Standardwert gesetzt.
  
-==== Teil V: Statische Methoden ====+ 
 +==== Teil V: Method Overriding ==== 
 + 
 +Schön wäre doch, wenn man einfach mit `Console.Writeline(v)` die Komponenten des Vektors schön ausgeben könnte. Wie du dich selbst vergewissern kannst, funktioniert dies (noch) nicht. 
 + 
 +`Console.Writeline` ruft jeweils die Klassenmethode `ToString()` auf. Für gewissen Datentypen wie ints wurde diese Methode bereits implementiert. Deshalb können solche Datentypen mit `Console.Writeline` angezeigt werden, obwohl sie keine Strings sind - sie werden vor der Anzeige in Strings umgewandelt. 
 + 
 +Implementiere die Methode `ToString()` für unsere Vektorklasse: 
 +<code csharp> 
 +public override String ToString() 
 +
 +    // YOUR CODE HERE 
 +
 +</code> 
 +Ein Vektor soll dann wie folgt ausgegeben werden: `[3,-42,7]` 
 +Vergewissere dich, dass `Console.Writeline` nun für Vektoren funktioniert. 
 + 
 + 
 +==== Teil VI: Statische Methoden ====
  
 Gegeben seien zwei Vektoren `v1` und `v2`. Möchten wir nun die Vektorsumme der beiden bestimmen, so haben wir zwei Möglichkeiten: `v1.Add(v2)` oder `v2.Add(v1)`. Im ersten Fall verwenden wir also die Klassenmethode `Add` des ersten Vektors und übergeben den zweiten Vektor als Argument. Schön wäre aber, wenn wir dies ohne die Klassenmethode machen könnten und einfach `Add(v1,v2)` schreiben könnten. Eine solche Methode heisst **statische Methode.** Sie ist //objektunabhängig//, gehört also //nicht// direkt zum Objekt. Wir könnten diese neue Add-Methode (`Add(v1,v2)`) deshalb in der Main-Methode deklarieren, was aber nicht sehr viel Sinn ergibt. Die Methode passt thematisch zur Vector-Klasse, da sie zwei Vektoren entgegennimmt, diese Addiert und dann wieder einen Vector zurückgibt. Deshalb liegt es auf der Hand, diese Methode als //statische// Methode in der Vector-Klasse zu definieren. Gegeben seien zwei Vektoren `v1` und `v2`. Möchten wir nun die Vektorsumme der beiden bestimmen, so haben wir zwei Möglichkeiten: `v1.Add(v2)` oder `v2.Add(v1)`. Im ersten Fall verwenden wir also die Klassenmethode `Add` des ersten Vektors und übergeben den zweiten Vektor als Argument. Schön wäre aber, wenn wir dies ohne die Klassenmethode machen könnten und einfach `Add(v1,v2)` schreiben könnten. Eine solche Methode heisst **statische Methode.** Sie ist //objektunabhängig//, gehört also //nicht// direkt zum Objekt. Wir könnten diese neue Add-Methode (`Add(v1,v2)`) deshalb in der Main-Methode deklarieren, was aber nicht sehr viel Sinn ergibt. Die Methode passt thematisch zur Vector-Klasse, da sie zwei Vektoren entgegennimmt, diese Addiert und dann wieder einen Vector zurückgibt. Deshalb liegt es auf der Hand, diese Methode als //statische// Methode in der Vector-Klasse zu definieren.
Zeile 86: Zeile 107:
  
  
-==== Teil V: Überladung von Operatoren ====+==== Teil VII: Überladung von Operatoren ====
  
 Noch praktischer wäre, wenn man einfach `v1 + v2` anstelle von `Add(v1,v2)` schreiben könnte. Dies ist möglich und heisst **Überladung von Operatoren**: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/operator-overloading Noch praktischer wäre, wenn man einfach `v1 + v2` anstelle von `Add(v1,v2)` schreiben könnte. Dies ist möglich und heisst **Überladung von Operatoren**: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/operator-overloading
Zeile 96: Zeile 117:
  
  
-==== Teil VI: Weitere Vektormethoden ====+==== Teil VIII: Weitere Vektormethoden ====
  
 Implementiere die folgenden, nützlichen Methoden für Vektoren. Implementiere die folgenden, nützlichen Methoden für Vektoren.
Zeile 105: Zeile 126:
  
  
-   1. `AngleInRad(v1,v2)` und `AngleInDeg(v1,v2)`: Bestimmt den Winkel (im Bogenmass und in Grad) zwischen den beiden Vektoren, siehe https://de.wikipedia.org/wiki/Skalarprodukt.  +   1. `AngleInRad(v1,v2)` und `AngleInDeg(v1,v2)`: Bestimmt den Winkel (im Bogenmass und in Grad) zwischen den beiden Vektoren, siehe https://de.wikipedia.org/wiki/Skalarprodukt. Achtung: Der Winkel zwischen zwei Vektoren ist nur definiert, falls //keiner// der beiden ein //Nullvektor// ist
-   2. `AreParallel(v1,v2)`, `AreAntiparallel (v1,v2)`, `AreParallelOrAntiparallel(v1,v2)`, `ArePerpendicular(v1,v2)` geben true/false zurück. Parallel heisst: zeigen in gleiche Richtung, Antiparallel heisst: zeigen in entgegengesetzte Richtung.+   2. `AreParallel(v1,v2)`, `AreAntiparallel (v1,v2)`, `AreParallelOrAntiparallel(v1,v2)`, `ArePerpendicular(v1,v2)` geben true/false zurück. Parallel heisst: zeigen in gleiche Richtung, Antiparallel heisst: zeigen in entgegengesetzte Richtung. Achtung auch wieder vor Nullvektoren!
    3. `SameLength(v1,v2)`: true/false    3. `SameLength(v1,v2)`: true/false
 +   4. Eigene Ideen
  
-==== Teil VII: Aufgaben ====+==== Teil IX: Aufgaben ====
  
 Öffne dein Dossier oder deine Aufgabenblätter aus dem Matheunterricht zum Thema Vektoren. Löse einige Aufgaben mithilfe deiner Vector-Klasse. Öffne dein Dossier oder deine Aufgabenblätter aus dem Matheunterricht zum Thema Vektoren. Löse einige Aufgaben mithilfe deiner Vector-Klasse.
  
  
 +<nodisp 2>
 +++++Lösung|
 +<code csharp>
 +using System;
 +namespace VectorMath
 +{
 +    public class Vector
 +    {
 +        public double[] Components;
 +        private double _accuracyDefault = 1e-15;
 +        private double _accuracyMax = 1e-1;
 +        private double _accuracy;
  
 +        // PROPERTIES
 +        public double Accuracy
 +        {
 +            get
 +            {
 +                return _accuracy;
 +            }
 +            set
 +            {
 +                if (value <= _accuracyMax)
 +                {
 +                    _accuracy = value;
 +                }
 +                else
 +                {
 +                    _accuracy = _accuracyDefault;
 +                }
 +            }
 +        }
 +
 +        public int Dimension
 +        {
 +            get
 +            {
 +                return Components.Length;
 +            }
 +        }
 +
 +        public double Magnitude
 +        {
 +            get
 +            {
 +                double magn = 0;
 +                foreach (var c in Components)
 +                {
 +                    magn += c * c;
 +                }
 +                return Math.Sqrt(magn);
 +            }
 +        }
 +
 +        public Vector UnitVector
 +        {
 +            get
 +            {
 +                double[] A = new double[Dimension];
 +                for (int i = 0; i < A.Length; i++)
 +                {
 +                    A[i] = Components[i] / Magnitude;
 +                }
 +                return new Vector(A);
 +            }
 +        }
 +
 +        public bool IsZeroVector
 +        {
 +            get
 +            {
 +                if (Magnitude < Accuracy)
 +                {
 +                    return true;
 +                }
 +                return false;
 +            }
 +        }
 +
 +        public bool IsUnitVector
 +        {
 +            get
 +            {
 +                double a = Math.Abs(Magnitude - 1);
 +                if (Math.Abs(Magnitude - 1) < Accuracy)
 +                {
 +                    return true;
 +                }
 +                return false;
 +            }
 +        }
 +
 +        // CONSTRUCTOR
 +        public Vector(double[] _components)
 +        {
 +            Components = _components;
 +            Accuracy = _accuracyDefault;
 +        }
 +
 +        public Vector(double[] _components, double _acc)
 +        {
 +            Components = _components;
 +            Accuracy = _acc;
 +        }
 +
 +        public Vector(double x, double y)
 +        {
 +            Components = new double[] { x, y };
 +            Accuracy = _accuracyDefault;
 +        }
 +
 +        public Vector(double x, double y, double z)
 +        {
 +            Components = new double[] { x, y, z };
 +            Accuracy = _accuracyDefault;
 +        }
 +
 +        // CLASS METHODS
 +
 +        public override String ToString()
 +        {
 +            // can now print vector with Console.Writeline
 +            string l = "[";
 +            for (int i = 0; i < Dimension - 1; i++)
 +            {
 +                l += Components[i].ToString() + ",";
 +
 +            }
 +            l += Components[Dimension - 1] + "]";
 +            return l;
 +        }
 +
 +        public Vector Add(Vector V)
 +        {
 +            checkIfSameDimension(V);
 +            double[] A = new double[Dimension];
 +            for (int i = 0; i < A.Length; i++)
 +            {
 +                A[i] = Components[i] + V.Components[i];
 +            }
 +            return new Vector(A);
 +        }
 +
 +        public Vector Sub(Vector V)
 +        {
 +            checkIfSameDimension(V);
 +            double[] A = new double[Dimension];
 +            for (int i = 0; i < A.Length; i++)
 +            {
 +                A[i] = Components[i] - V.Components[i];
 +            }
 +            return new Vector(A);
 +        }
 +
 +        public double DotProduct(Vector V)
 +        {
 +            checkIfSameDimension(V);
 +            double d = 0;
 +            for (int i = 0; i < Dimension; i++)
 +            {
 +                d += Components[i] * V.Components[i];
 +            }
 +            return d;
 +        }
 +
 +        public Vector ScalarMultiplication(double s)
 +        {
 +            double[] A = new double[Dimension];
 +            for (int i = 0; i < A.Length; i++)
 +            {
 +                A[i] = s * Components[i];
 +            }
 +            return new Vector(A);
 +        }
 +
 +        public double AngleInRad(Vector v)
 +        {
 +            if (IsZeroVector)
 +            {
 +                raiseZeroVectorError();
 +            }
 +            else if (v.IsZeroVector)
 +            {
 +                v.raiseZeroVectorError();
 +            }
 +
 +            return Math.Acos(DotProduct(this, v) / (this.Magnitude * v.Magnitude));
 +        }
 +
 +        public double AngleInDeg(Vector v)
 +        {
 +            return AngleInRad(v) * 180 / Math.PI;
 +        }
 +
 +        public bool AreParallel(Vector v)
 +        {
 +            if (Math.Abs(AngleInRad(v)) < Accuracy) { return true; }
 +            else { return false; }
 +        }
 +
 +        public bool AreAntiparallel(Vector v)
 +        {
 +            if (Math.Abs(AngleInRad(v) - Math.PI) < Accuracy) { return true; }
 +            else { return false; }
 +        }
 +
 +        public bool AreParallelOrAntiparallel(Vector v)
 +        {
 +            if (AreParallel(v) || AreAntiparallel(v)) { return true; }
 +            else { return false; }
 +        }
 +
 +        public bool ArePerpendicular(Vector v)
 +        {
 +            if (Math.Abs(AngleInRad(v) - Math.PI / 2) < Accuracy) { return true; }
 +            else { return false; }
 +        }
 +
 +        public bool HaveSameMagnitude(Vector v)
 +        {
 +            if (Math.Abs(Magnitude - v.Magnitude) < Accuracy) { return true; }
 +            else { return false; }
 +        }
 +
 +        private void checkIfSameDimension(Vector V)
 +        {
 +            if (V.Dimension != Dimension)
 +            {
 +                throw new Exception("Wrong dimension ERROR!");
 +            }
 +        }
 +
 +        private void raiseZeroVectorError()
 +        {
 +
 +            throw new Exception("Zero Vector Exception!");
 +
 +        }
 +
 +        // STATIC METHODS
 +        public static Vector ZeroVector(int n)
 +        {
 +            double[] a = new double[n];
 +            for (int i = 0; i < n; i++)
 +            {
 +                a[i] = 0;
 +            }
 +            return new Vector(a);
 +        }
 +
 +        public static Vector Add(Vector v1, Vector v2)
 +        {
 +            return v1.Add(v2);
 +        }
 +
 +        public static Vector Sub(Vector v1, Vector v2)
 +        {
 +            return v1.Sub(v2);
 +        }
 +
 +        public static double DotProduct(Vector v1, Vector v2)
 +        {
 +            return v1.DotProduct(v2);
 +        }
 +
 +        public static Vector ScalarMultiplication(double s, Vector v)
 +        {
 +            return v.ScalarMultiplication(s);
 +        }
 +
 +        public static Vector ScalarMultiplication(Vector v, double s)
 +        {
 +            return v.ScalarMultiplication(s);
 +        }
 +
 +        public static Vector ScalarProduct(Vector v1, Vector v2)
 +        {
 +            if (v1.Dimension != 3 && v2.Dimension != 3)
 +            {
 +                throw new Exception("Wrong dimension ERROR!");
 +            }
 +            double[] a = new double[3];
 +            a[0] = v1.Components[1] * v2.Components[2] - v1.Components[2] * v2.Components[1];
 +            a[1] = v1.Components[2] * v2.Components[0] - v1.Components[0] * v2.Components[2];
 +            a[2] = v1.Components[0] * v2.Components[1] - v1.Components[1] * v2.Components[0];
 +            return new Vector(a);
 +        }
 +
 +        public static double AngleInRad(Vector v1, Vector v2)
 +        {
 +            return v1.AngleInRad(v2);
 +        }
 +
 +        public static double AngleInDeg(Vector v1, Vector v2)
 +        {
 +            return v1.AngleInDeg(v2);
 +        }
 +
 +        // OPERATOR OVERLOADING 
 +        public static Vector operator +(Vector v) => v;
 +        public static Vector operator -(Vector v) => ZeroVector(v.Dimension) - v;
 +
 +        public static Vector operator +(Vector v1, Vector v2) => Add(v1, v2);
 +        public static Vector operator -(Vector v1, Vector v2) => Sub(v1, v2);
 +        public static double operator *(Vector v1, Vector v2) => DotProduct(v1, v2);
 +        public static Vector operator *(Vector v, double s) => ScalarMultiplication(s, v);
 +        public static Vector operator *(double s, Vector v) => ScalarMultiplication(s, v);
 +
 +    }
 +}
 +</code>
 +++++
 +</nodisp>
  • ef_informatik/csharp_oop.1648549904.txt.gz
  • Zuletzt geändert: 2022-03-29 10:31
  • von sca