Unbekannte Dezimalzahl als Bruch
- VB.NET
Sie verwenden einen veralteten Browser (%browser%) mit Sicherheitsschwachstellen und können nicht alle Funktionen dieser Webseite nutzen.
Hier erfahren Sie, wie einfach Sie Ihren Browser aktualisieren können.
Hier erfahren Sie, wie einfach Sie Ihren Browser aktualisieren können.
Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von ~blaze~.
-
-
x und 1 sind in jedem Falle eine Triviallösung.
Kannst Du mal ein Beispiel machen?Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch
Ein guter .NET-Snippetkonverter (der ist verfügbar).
Programmierfragen über PN / Konversation werden ignoriert! -
Ich hatte da mal was gemacht, ist schon etwas länger her, also kann es sein, dass es an manchen Stellen etwas unsauber ist, aber vielleicht kannst du ja was damit anfangen.
Spoiler anzeigen VB.NET-Quellcode
- ''' <summary>
- ''' Stellt einen Bruch dar, der sich automatisch kürzt und der die Konvertierung von und in Dezimalzahlen unterstützt.
- ''' </summary>
- ''' <remarks></remarks>
- Public Structure Fraction
- Private m_Numerator As Long
- Private m_Denominator As Long
- Private m_DecimalValue As Decimal
- Public ReadOnly Property isZero As Boolean
- Get
- Return m_Numerator = 0 OrElse m_Denominator = 0
- End Get
- End Property
- ''' <summary>
- ''' Der Zähler des Bruches.
- ''' </summary>
- ''' <value></value>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Property numerator As Long
- Get
- Return m_Numerator
- End Get
- Set(value As Long)
- If value = 0 Then
- m_Numerator = 0
- m_DecimalValue = 0D
- Exit Property
- End If
- If m_Denominator = 0 Then
- m_Numerator = value
- Exit Property
- End If
- Dim gcd As Long = MathUtils.GetGreatestCommonDivisor(value, m_Denominator)
- m_Numerator = value \ gcd
- m_Denominator = m_Denominator \ gcd
- m_DecimalValue = Convert.ToDecimal(m_Numerator) / Convert.ToDecimal(m_Denominator)
- End Set
- End Property
- ''' <summary>
- ''' Der Nenner des Bruches.
- ''' </summary>
- ''' <value></value>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Property denominator As Long
- Get
- Return m_Denominator
- End Get
- Set(value As Long)
- If value = 0 Then
- m_Denominator = 0
- m_DecimalValue = 0D
- Exit Property
- End If
- If m_Numerator = 0 Then
- m_Denominator = value
- Exit Property
- End If
- Dim gcd As Long = MathUtils.GetGreatestCommonDivisor(m_Numerator, value)
- m_Numerator = m_Numerator \ gcd
- m_Denominator = value \ gcd
- m_DecimalValue = Convert.ToDecimal(m_Numerator) / Convert.ToDecimal(m_Denominator)
- End Set
- End Property
- ''' <summary>
- ''' Die Darstellung des Bruches als Dezimalzahl.
- ''' </summary>
- ''' <value></value>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Property decimalValue As Decimal
- Get
- Return m_DecimalValue
- End Get
- Set(value As Decimal)
- If value = 0 Then
- m_Numerator = 0
- m_Denominator = 0
- m_DecimalValue = 0D
- Exit Property
- End If
- Dim movedDecimals As Integer
- Dim intValue As BigInteger = getBigInt(value, movedDecimals)
- Dim exponent As New BigInteger(10 ^ movedDecimals)
- Dim gcd As BigInteger = BigInteger.GreatestCommonDivisor(intValue, exponent)
- m_Numerator = Long.Parse((intValue / gcd).ToString)
- m_Denominator = Long.Parse((exponent / gcd).ToString)
- m_DecimalValue = Convert.ToDecimal(m_Numerator) / Convert.ToDecimal(m_Denominator)
- End Set
- End Property
- Private Function getBigInt(ByVal val As Decimal, ByRef movedDecimals As Integer) As BigInteger
- Dim nF As NumberFormatInfo = CultureInfo.InvariantCulture.NumberFormat
- Dim s As String = val.ToString(nF).ToLowerInvariant
- Dim decSep As String = nF.NumberDecimalSeparator
- Dim pot As String = "e+"
- If s.Contains(pot) Then
- Dim parts() As String = s.Split({pot}, StringSplitOptions.RemoveEmptyEntries)
- Dim base As String = parts(0)
- Dim exponent As Integer = Integer.Parse(parts(1))
- If base.Contains(decSep) Then
- Dim i As Integer = base.IndexOf(decSep)
- movedDecimals = exponent + (base.Length - (i + decSep.Length))
- Return BigInteger.Parse(base.Remove(i, decSep.Length), nF) * exponent
- Else
- movedDecimals = exponent
- Return BigInteger.Parse(base, nF) * exponent
- End If
- ElseIf s.Contains(decSep) Then
- Dim i As Integer = s.IndexOf(decSep)
- movedDecimals = s.Length - (i + decSep.Length)
- Return BigInteger.Parse(s.Remove(i, decSep.Count), nF)
- Else
- Return BigInteger.Parse(s, nF)
- End If
- End Function
- ''' <summary>
- ''' Erstellt einen neuen Bruch aus Zähler und Nenner.
- ''' </summary>
- ''' <param name="denom">Der Nenner des Bruches.</param>
- ''' <param name="num">Der Zähler des Bruches.</param>
- ''' <remarks></remarks>
- Sub New(ByVal num As Long, ByVal denom As Long)
- If num = 0 OrElse denom = 0 Then
- m_Numerator = num
- m_Denominator = denom
- Exit Sub
- End If
- Dim gcd As Long = MathUtils.GetGreatestCommonDivisor(num, denom)
- m_Denominator = denom \ gcd
- m_Numerator = num \ gcd
- m_DecimalValue = Convert.ToDecimal(m_Numerator) / Convert.ToDecimal(m_Denominator)
- End Sub
- ''' <summary>
- ''' Erstellt einen neuen Bruch aus einer Dezimalzahl.
- ''' </summary>
- ''' <param name="decVal"></param>
- ''' <remarks></remarks>
- Sub New(ByVal decVal As Decimal)
- decimalValue = decVal
- End Sub
- ''' <summary>
- ''' Erstellt einen neuen Bruch aus einer Dezimalzahl.
- ''' </summary>
- ''' <param name="decVal"></param>
- ''' <remarks></remarks>
- Sub New(ByVal decVal As Double)
- decimalValue = Convert.ToDecimal(decVal)
- End Sub
- ''' <summary>
- ''' Erstellt einen neuen Bruch aus einem anderen.
- ''' </summary>
- ''' <param name="f"></param>
- ''' <remarks></remarks>
- Sub New(ByVal f As Fraction)
- m_Numerator = f.m_Numerator
- m_Denominator = f.m_Denominator
- m_DecimalValue = f.m_DecimalValue
- End Sub
- ''' <summary>
- ''' Konvertiert diesen Bruch in seine eintsprechende Zeichenfolgendarstellung.
- ''' </summary>
- ''' <returns></returns>
- ''' <remarks></remarks>
- Public Overrides Function ToString() As String
- Return String.Concat({Me.GetType.FullName, ": ", numerator.ToString, "/", denominator.ToString, " {", decimalValue.ToString, "}"})
- End Function
- Public Shared Operator +(ByVal v1 As Fraction, ByVal v2 As Double) As Double
- Return v1.decimalValue + v2
- End Operator
- Public Shared Operator +(ByVal v1 As Double, ByVal v2 As Fraction) As Double
- Return v1 + v2.decimalValue
- End Operator
- Public Shared Operator -(ByVal v1 As Fraction, ByVal v2 As Double) As Double
- Return v1.decimalValue - v2
- End Operator
- Public Shared Operator -(ByVal v1 As Double, ByVal v2 As Fraction) As Double
- Return v1 - v2.decimalValue
- End Operator
- Public Shared Operator *(ByVal v1 As Fraction, ByVal v2 As Double) As Double
- Return v1.decimalValue * v2
- End Operator
- Public Shared Operator *(ByVal v1 As Double, ByVal v2 As Fraction) As Double
- Return v1 * v2.decimalValue
- End Operator
- Public Shared Operator /(ByVal v1 As Fraction, ByVal v2 As Double) As Double
- Return v1.decimalValue / v2
- End Operator
- Public Shared Operator /(ByVal v1 As Double, ByVal v2 As Fraction) As Double
- Return v1 / v2.decimalValue
- End Operator
- Public Shared Operator =(ByVal v1 As Fraction, ByVal v2 As Fraction) As Boolean
- Return v1.numerator = v2.numerator AndAlso v1.denominator = v2.denominator
- End Operator
- Public Shared Operator <>(ByVal v1 As Fraction, ByVal v2 As Fraction) As Boolean
- Return Not v1 = v2
- End Operator
- Public Shared Operator <(ByVal v1 As Fraction, ByVal v2 As Fraction) As Boolean
- Return v1.decimalValue < v2.decimalValue
- End Operator
- Public Shared Operator <(ByVal v1 As Fraction, ByVal v2 As Double) As Boolean
- Return v1.decimalValue < v2
- End Operator
- Public Shared Operator <(ByVal v1 As Double, ByVal v2 As Fraction) As Boolean
- Return v1 < v2.decimalValue
- End Operator
- Public Shared Operator >(ByVal v1 As Fraction, ByVal v2 As Fraction) As Boolean
- Return v1.decimalValue > v2.decimalValue
- End Operator
- Public Shared Operator >(ByVal v1 As Fraction, ByVal v2 As Double) As Boolean
- Return v1.decimalValue > v2
- End Operator
- Public Shared Operator >(ByVal v1 As Double, ByVal v2 As Fraction) As Boolean
- Return v1 > v2.decimalValue
- End Operator
- Public Shared Operator <=(ByVal v1 As Fraction, ByVal v2 As Fraction) As Boolean
- Return v1.decimalValue <= v2.decimalValue
- End Operator
- Public Shared Operator <=(ByVal v1 As Fraction, ByVal v2 As Double) As Boolean
- Return v1.decimalValue <= v2
- End Operator
- Public Shared Operator <=(ByVal v1 As Double, ByVal v2 As Fraction) As Boolean
- Return v1 >= v2.decimalValue
- End Operator
- Public Shared Operator >=(ByVal v1 As Fraction, ByVal v2 As Fraction) As Boolean
- Return v1.decimalValue >= v2.decimalValue
- End Operator
- Public Shared Operator >=(ByVal v1 As Fraction, ByVal v2 As Double) As Boolean
- Return v1.decimalValue >= v2
- End Operator
- Public Shared Operator >=(ByVal v1 As Double, ByVal v2 As Fraction) As Boolean
- Return v1 >= v2.decimalValue
- End Operator
- End Structure
- End Namespace
-
RodFromGermany schrieb:
x und 1 sind in jedem Falle eine Triviallösung.
Es kann sein dass ich mich etwas undeutlich ausgedrückt habe. Unbekannt ist die Zahl nicht direkt, aber ich kann vorher nicht ahnen welche Zahl es wird. (Ähnlich wie Zufallsprinzip)
Undzwar geht es darum dass ausgehend von einem String jeweils 3 Koordinaten gebildet werden. Anhand dieser 3 berechne ich eine Funktionsgleichung.
Jenachdem welche Koordinaten dabei sind wird ein Koeffizient (a,b,c) periodisch. Ich muss anschließend allerdings noch mit ihnen rechnen und in periodischer Form ist das nicht so toll.
Außerdem möchte ich das Gauschverfahren (Aufstellen der Gleichung) direkt mit Brüchen machen, damit ich nicht nachher bei den Decimalzahlen einen Überlauf bekomme.
Als Beispiel kann man jede beliebige Zahl nehmen. -
LaMiy schrieb:
Was meinst du damit ?
Gugst Du "Größter gemeinsamer Teiler" und "Kleinstes gemeinsames Vielfaches" als kleine Lektüre zur Zahlentheorie.Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch
Ein guter .NET-Snippetkonverter (der ist verfügbar).
Programmierfragen über PN / Konversation werden ignoriert! -
Eine periodische Darstellung ist mit normalen Datentypen nicht möglich, denn eine periodische Zahl würde unendlich Speicher benötigen. Du könntest zwar eine spezielle Klasse dafür schreiben, jedoch musst du dann alle Rechenoperationen selbst implementieren, wobei ich nicht mal wüsste, wie man sowas angehen könnte. Auch meine Bruch-Klasse unterstützt keine Periodischen Zahlen, denn der Bruch wird aus einer Dezimalzahl gebildet und diese kann ja nicht periodisch sein.
-
RodFromGermany schrieb:
Deine Zahl sei x, dann ist x / 1 eine "Triviallösung".
Dann hab ich es aber ja im Zähler stehen
@Artentus
Ich meine sowas wie 0,3333333333 = 1/3 = "Ein Drittel" -
-
Das ist mir schon klar, aber 0,3333333333 ist eben nicht 1/3, sondern ein bisschen weniger. Ein Double kann maximal 15 Stellen darstellen, dann ist Schluss, und auch mit 15 Dreiern hast du 1/3 noch nicht erreicht.
Ich denke du solltest die Sache anders angehen. Eine periodische Zahl entsteht ja durch eine Division. Statt diese auszurechnen kannst du sie auch gleich als Bruch sehen und dann damit weiterrechnen. -
-
Hi,
es bestände die Möglichkeit den Dezimalbruch zu runden. Damit erzielst du zwar ebenfalls ne Abweichung, aber anders geht es ja nicht, denn VB bietet zwar die Möglichkeit mit Gleitkommazahlen zu arbeiten, allerdings können diese bei Zahlen, die sich nur geringfügig von 0 unterscheiden bereits den Verlust von gültigen Stellen im Dezimalbruch auslösen.
Insbesondere iterativ arbeitende Algorithmen können auf die daraus resultierende Fehlerakkumulation im Einzelfall sehr negativ reagieren und liefern dann normalerweise sogar extrem ungenaue Resultate.
So musst du dann deine eigene Klasse aufbauen und eben die Datentypen durchprobieren. Was halt dann am Besten passt.
Ich schlage Long oder ggf sogar Decimal vor. Den Rest musst du halt dann alleine lösen, aber du hast ja bereits mehrere Anfangshilfen bekommen.
Gruß Trade#define for for(int z=0;z<2;++z)for // Have fun!
Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose!
Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da -
@LaMiy:: Das war das Beispiel.
Iwo in meinem Hinterkopf steckt noch drin, dass gewisse periodische Brüche gewissen (mathematischen) Gesetzmäßigkeiten unterliegen, z.B. eine 6-stellige Perriode:
1 / 7 = 0,142857'142857'142857'142857'14285714
Genaueres weiß ich dazu nicht.
-----
Interessant ist es auch, solch Brüche in einem anderen Zahlensystem zu betrachten, z.B. im Duo-Dezimalsystem. Da die Basis 12 durch 3 teilbar ist, wäre { (1 / 3) = 0,4 | Basis = 12 }.Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch
Ein guter .NET-Snippetkonverter (der ist verfügbar).
Programmierfragen über PN / Konversation werden ignoriert! -
Das wird anscheinend so eine Art Verschlüsselung, bei der die Zahlen zu Strings konvertiert werden sollen. Statt sie dann in Strings zu konvertieren wäre es sinnvoll, direkt die Rohdaten in Byteform abzuspeichern, also 8 Bytes für Rational64 = UInteger/Integer. Macht sicherheitstechnisch kaum einen Unterschied, ob man das jetzt aus Bytes zurückrechnet oder aus einem String. Performancetechnisch sind natürlich für Bytes wesentlich weniger Operationen nötig.
Gruß
~blaze~
-
Ähnliche Themen
-
__JOEY__ - - Sonstige Problemstellungen
-
Chris213 - - Sonstige Problemstellungen
-
-
5 Benutzer haben hier geschrieben
- LaMiy (4)
- RodFromGermany (3)
- Artentus (3)
- ~blaze~ (2)
- Trade (1)