C# :: Aufgabe #216
2 Lösungen

Brüche und überladene Operatoren
Anfänger - C#
von Exception
- 09.06.2018 um 09:07 Uhr
- Erstelle eine Klasse "Bruch"
- In dieser Klasse gibt es zwei Attribute: Zähler, Nenner (jeweils Integer)
- In dieser Klasse gibt es zudem noch überladene Opteratoren (+, -, *, /)
Diese Operatoren haben jeweils zwei Parameter, die übergeben werden müssen -> zwei Objekte der Klasse Bruch.
Die Operatoren geben einen neuen Bruch zurück.
In der Hauptmethode (oder sonst wo) soll dann folgendes möglich sein:
C#-Code
- Die Klasse Bruch braucht für das Teilen von Brüchen evtl. noch ein bisschen mehr... #Methoden ;)
- Das Anlegen / Erzeugen von Brüchen soll mit Textboxen realisiert werden, sodass das ganze Programm grafisch etwas her macht.
- Die Rechenopertation (+,-,*,/) soll mit einer Dropdown Liste o.ä. ausgewählt werden.
- Mit einem Button soll die Berechnung starten und das Ergebnis anschließend in zwei weitere Textboxen (read only) geschrieben werden.
- Damit die Brüche nicht zu groß werden (50/100 o.ä.) soll bevor das Ergebnis in die Textbox geschrieben wird geschaut werden, ob sich der neue Bruch kürzen lässt.
- In dieser Klasse gibt es zwei Attribute: Zähler, Nenner (jeweils Integer)
- In dieser Klasse gibt es zudem noch überladene Opteratoren (+, -, *, /)
Diese Operatoren haben jeweils zwei Parameter, die übergeben werden müssen -> zwei Objekte der Klasse Bruch.
Die Operatoren geben einen neuen Bruch zurück.
In der Hauptmethode (oder sonst wo) soll dann folgendes möglich sein:

Bruch b1 = new Bruch(1, 2); Bruch b2 = new Bruch(3, 4); Bruch b3 = b1 + b2; // auch -, *, /
- Die Klasse Bruch braucht für das Teilen von Brüchen evtl. noch ein bisschen mehr... #Methoden ;)
- Das Anlegen / Erzeugen von Brüchen soll mit Textboxen realisiert werden, sodass das ganze Programm grafisch etwas her macht.
- Die Rechenopertation (+,-,*,/) soll mit einer Dropdown Liste o.ä. ausgewählt werden.
- Mit einem Button soll die Berechnung starten und das Ergebnis anschließend in zwei weitere Textboxen (read only) geschrieben werden.
- Damit die Brüche nicht zu groß werden (50/100 o.ä.) soll bevor das Ergebnis in die Textbox geschrieben wird geschaut werden, ob sich der neue Bruch kürzen lässt.
Lösungen:
BruchC Klasse
C#-Code
MainWindow.xaml
MainWindow.xaml.cs
C#-Code

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Bruch { public class BruchC { public double zaehler { get; set; } public double nenner { get; set; } public BruchC(double zaehler, double nenner) { this.zaehler = zaehler; this.nenner = nenner; } public static BruchC operator +(BruchC b1, BruchC b2) { bruchKuerzen(ref b1, ref b2); if (b1.nenner == b2.nenner) { return new BruchC(b1.zaehler + b2.zaehler, b1.nenner); } else { return new BruchC(b1.zaehler * b2.nenner + b2.zaehler * b1.nenner, b1.nenner * b2.nenner); } } public static BruchC operator -(BruchC b1, BruchC b2) { bruchKuerzen(ref b1, ref b2); if (b1.nenner == b2.nenner) { return new BruchC(b1.zaehler - b2.zaehler, b1.nenner); } else { return new BruchC(b1.zaehler * b2.nenner - b2.zaehler * b1.nenner, b1.nenner * b2.nenner); } } public static BruchC operator *(BruchC b1, BruchC b2) { bruchKuerzen(ref b1, ref b2); return new BruchC(b1.zaehler * b2.zaehler, b1.nenner * b2.nenner); } public static BruchC operator /(BruchC b1, BruchC b2) { BruchC newB2 = new BruchC(b2.nenner, b2.zaehler); BruchC newB = b1* newB2; bruchKuerzen(ref newB2, ref newB); return newB; } private static void bruchKuerzen(ref BruchC b1, ref BruchC b2) { if (b1 != null) for (double i = b1.nenner; i >= 0; i--) { if (b1.nenner % i == 0 && b1.zaehler % i == 0) { b1.nenner /= i; b1.zaehler /= i; break; } } if (b2 != null) for (double i = b2.nenner; i >= 0; i--) { if (b2.nenner % i == 0 && b2.zaehler % i == 0) { b2.nenner /= i; b2.zaehler /= i; break; } } } } }
MainWindow.xaml
<Window x:Class="Bruch.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Bruch"
mc:Ignorable="d"
Title="Bruch Rechner" Height="180.932" Width="249.153" WindowStyle="ToolWindow" ResizeMode="NoResize">
<Grid>
<TextBox x:Name="z1" PreviewTextInput="NumberValidationTextBox" HorizontalAlignment="Left" Height="27" Margin="21,19,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="27" TextAlignment="Center"/>
<TextBox x:Name="n1" PreviewTextInput="NumberValidationTextBox" HorizontalAlignment="Left" Height="27" Margin="21,51,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="27" TextAlignment="Center"/>
<TextBox x:Name="z2" PreviewTextInput="NumberValidationTextBox" HorizontalAlignment="Left" Height="27" Margin="97,19,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="27" TextAlignment="Center"/>
<TextBox x:Name="n2" PreviewTextInput="NumberValidationTextBox" HorizontalAlignment="Left" Height="27" Margin="97,51,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="27" TextAlignment="Center"/>
<TextBox x:Name="z3" HorizontalAlignment="Left" Height="27" Margin="166,19,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="27" IsReadOnly="True" TextAlignment="Center"/>
<TextBox x:Name="n3" HorizontalAlignment="Left" Height="27" Margin="166,51,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="27" IsReadOnly="True" TextAlignment="Center"/>
<Label Content="=
" HorizontalAlignment="Left" Margin="142,33,0,0" VerticalAlignment="Top" Height="31" Width="19"/>
<Button Content="Rechne" HorizontalAlignment="Left" Margin="21,97,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
<ComboBox x:Name="opr" HorizontalAlignment="Left" Margin="54,37,0,0" VerticalAlignment="Top" Width="38" Height="27" SelectedIndex="0"/>
</Grid>
</Window>
MainWindow.xaml.cs

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace Bruch { /// <summary> /// Interaktionslogik für MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); opr.Items.Add("+"); opr.Items.Add("-"); opr.Items.Add("*"); opr.Items.Add("/"); } private void NumberValidationTextBox(object sender, TextCompositionEventArgs e) { var textBox = sender as TextBox; e.Handled = Regex.IsMatch(e.Text, "[^0-9]+"); } private void Button_Click(object sender, RoutedEventArgs e) { BruchC b1 = new BruchC(Convert.ToDouble(z1.Text), Convert.ToDouble(n1.Text)); BruchC b2 = new BruchC(Convert.ToDouble(z2.Text), Convert.ToDouble(n2.Text)); BruchC b3 = null; switch (opr.SelectedItem) { case "+": b3 = b1 + b2; break; case "-": b3 = b1 - b2; break; case "*": b3 = b1 * b2; break; case "/": b3 = b1 / b2; break; } z3.Text = Convert.ToString(b3.zaehler); n3.Text = Convert.ToString(b3.nenner); } } }
MainWindow.xaml.cs
C#-Code
MainWindow.xaml
XML-Code
Fraction.cs
C#-Code

using System.Windows; namespace WpfBruchrechner { /// <summary> /// Interaktionslogik für MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void buttonCalc_Click(object sender, RoutedEventArgs e) { int le, ld, re, rd; if (int.TryParse(textBoxEnumeratorLeft.Text, out le) && int.TryParse(textBoxDenominatorLeft.Text, out ld) && int.TryParse(textBoxEnumeratorRight.Text, out re) && int.TryParse(textBoxDenominatorRight.Text, out rd) && ld != 0 && rd != 0) { Fraction left = new Fraction(le, ld); Fraction right = new Fraction(re, rd); Fraction result; string action = comboBoxAction.SelectedItem.ToString(); switch (action) { case "+": result = left + right; break; case "-": result = left - right; break; case "*": result = left * right; break; case "/": if (re == 0) { MessageBox.Show("Eingaben ungültig!", "", MessageBoxButton.OK, MessageBoxImage.Warning); return; } result = left / right; break; default: result = new Fraction(0, 0); break; } textBoxEnumeratorResult.Text = result.Enumerator.ToString(); textBoxDenominatorResult.Text = result.Denominator.ToString(); } else { MessageBox.Show("Eingaben ungültig!", "", MessageBoxButton.OK, MessageBoxImage.Warning); } } } }
MainWindow.xaml

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfBruchrechner" xmlns:System="clr-namespace:System;assembly=mscorlib" x:Class="WpfBruchrechner.MainWindow" mc:Ignorable="d" Title="Bruchrechner" SizeToContent="WidthAndHeight" ResizeMode="CanMinimize"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid Grid.Row="0"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Grid Grid.Column="0" Margin="10"> <TextBox x:Name="textBoxEnumeratorLeft" HorizontalAlignment="Left" Height="23" Margin="54,10,0,0" TextWrapping="Wrap" Text="1" VerticalAlignment="Top" Width="50" TextAlignment="Center"/> <TextBlock x:Name="textBlock" HorizontalAlignment="Left" Margin="10,13,0,0" TextWrapping="Wrap" Text="Zähler" VerticalAlignment="Top"/> <TextBox x:Name="textBoxDenominatorLeft" HorizontalAlignment="Left" Height="23" Margin="54,38,0,0" TextWrapping="Wrap" Text="1" VerticalAlignment="Top" Width="50" TextAlignment="Center"/> <TextBlock x:Name="textBlock1" HorizontalAlignment="Left" Margin="10,41,0,0" TextWrapping="Wrap" Text="Nenner" VerticalAlignment="Top"/> </Grid> <ComboBox x:Name="comboBoxAction" Grid.Column="1" Width="50" Height="23" SelectedIndex="0"> <System:String>+</System:String> <System:String>-</System:String> <System:String>*</System:String> <System:String>/</System:String> </ComboBox> <Grid Grid.Column="2" Margin="10"> <TextBox x:Name="textBoxEnumeratorRight" HorizontalAlignment="Left" Height="23" Margin="54,10,0,0" TextWrapping="Wrap" Text="1" VerticalAlignment="Top" Width="50" TextAlignment="Center"/> <TextBlock x:Name="textBlock2" HorizontalAlignment="Left" Margin="10,13,0,0" TextWrapping="Wrap" Text="Zähler" VerticalAlignment="Top"/> <TextBox x:Name="textBoxDenominatorRight" HorizontalAlignment="Left" Height="23" Margin="54,38,0,0" TextWrapping="Wrap" Text="1" VerticalAlignment="Top" Width="50" TextAlignment="Center"/> <TextBlock x:Name="textBlock3" HorizontalAlignment="Left" Margin="10,41,0,0" TextWrapping="Wrap" Text="Nenner" VerticalAlignment="Top"/> </Grid> </Grid> <Grid Grid.Row="1"> <Button x:Name="buttonCalc" Margin="10" Content="=" Click="buttonCalc_Click"/> </Grid> <Grid Grid.Row="2"> <Grid HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10"> <TextBox x:Name="textBoxEnumeratorResult" HorizontalAlignment="Left" Height="23" Margin="54,10,0,0" TextWrapping="Wrap" Text="1" VerticalAlignment="Top" Width="50" TextAlignment="Center"/> <TextBlock x:Name="textBlock4" HorizontalAlignment="Left" Margin="10,13,0,0" TextWrapping="Wrap" Text="Zähler" VerticalAlignment="Top"/> <TextBox x:Name="textBoxDenominatorResult" HorizontalAlignment="Left" Height="23" Margin="54,38,0,0" TextWrapping="Wrap" Text="1" VerticalAlignment="Top" Width="50" TextAlignment="Center"/> <TextBlock x:Name="textBlock5" HorizontalAlignment="Left" Margin="10,41,0,0" TextWrapping="Wrap" Text="Nenner" VerticalAlignment="Top"/> </Grid> </Grid> </Grid> </Window>
Fraction.cs

using System; using System.Collections.Generic; using System.Linq; namespace WpfBruchrechner { public class Fraction { private int enumerator; public int Enumerator { get { return enumerator; } set { enumerator = value; } }//Zähler private int denominator; public int Denominator { get { return denominator; } set { denominator = value; } }//Nenner public Fraction(int enumerator, int denominator) { this.enumerator = enumerator; this.denominator = denominator; } public override string ToString() { return $"{Enumerator}/{Denominator}"; } public void Short() { ShortFraction(ref enumerator, ref denominator); } public void Expand(int v) { if (v != 0) { enumerator *= v; denominator *= v; } } public Fraction Inverse() { return new Fraction(denominator, enumerator); } //Operatoren public static Fraction operator +(Fraction left, Fraction right) { int kgv = GetLowestCommenMultiple(left.Denominator, right.Denominator); Fraction l = left; Fraction r = right; l.Expand(kgv / l.Denominator); r.Expand(kgv / r.Denominator); Fraction ret = l; ret.Enumerator += r.Enumerator; ret.Short(); return ret; } public static Fraction operator -(Fraction left, Fraction right) { int kgv = GetLowestCommenMultiple(left.Denominator, right.Denominator); Fraction l = new Fraction(left.Enumerator, left.Denominator); Fraction r = new Fraction(right.Enumerator, right.Denominator); l.Expand(kgv / l.Denominator); r.Expand(kgv / r.Denominator); Fraction ret = l; ret.Enumerator -= r.Enumerator; ret.Short(); return ret; } public static Fraction operator *(Fraction left, Fraction right) { Fraction ret = new Fraction(left.Enumerator * right.Enumerator, left.Denominator * right.Denominator); ret.Short(); return ret; } public static Fraction operator /(Fraction left, Fraction right) { Fraction ret = new Fraction(left.Enumerator * right.Denominator, left.Denominator * right.Enumerator); ret.Short(); return ret; } //KGV private static Dictionary<int, int> PrimeFactorization(int a) { Dictionary<int, int> primes = new Dictionary<int, int>(); for (int b = 2; a > 1; b++) { if (a % b == 0) { int x = 0; while (a % b == 0) { a /= b; x++; } primes.Add(b, x); } } return primes; } private static int GetLowestCommenMultiple(params int[] source) { var distinct = source.Distinct(); var divs = from i in distinct select PrimeFactorization(i); Dictionary<int, int> result = new Dictionary<int, int>(); foreach (var dic in divs) { foreach (var item in dic) { if (result.ContainsKey(item.Key)) { if (result[item.Key] < item.Value) { result[item.Key] = item.Value; } } else { result.Add(item.Key, item.Value); } } } int mul = 1; foreach (var item in result) { mul *= (int)Math.Pow(item.Key, item.Value); } return mul; } //Kettenbruch private static void ShortFraction(ref int enumerator, ref int denominator) { int[] fraction = GetContinuedFraction(enumerator, denominator); TransformContinuedFraction(fraction, out enumerator, out denominator); } private static void TransformContinuedFraction(int[] fraction, out int enumerator, out int denominator) { if (fraction.Length == 1) { enumerator = fraction[0]; denominator = 1; } else if (fraction.Length >= 2) { int zl = 1; int nl = fraction[fraction.Length - 1]; int zt = zl; int nt = nl; for (int i = fraction.Length - 2; i >= 1; i--) { zt += (nt * fraction[i]); int t1 = zt; int t2 = nt; zt = t2; nt = t1; } enumerator = zt + (fraction[0] * nt); denominator = nt; } else { throw new ArgumentException(); } } private static int[] GetContinuedFraction(int z, int n) { int zt = z; int nt = n; int za = (z % n); int a = (z - (za)) / n; if (za == 0) { return new int[1] { a }; } int b = n / za; List<int> result = new List<int>() { a, b }; int c = n % za; while (c != 0) { int t = za % c; result.Add(za / c); za = c; c = t; } return result.ToArray(); } } }