Seite 1 von 4

Dezimalzahlen in Bruch umwandeln

Verfasst: 14.11.2011 21:44
von marl
Hallo, ich weiss nicht ob ich hier richtig bin.
Ich muss in meinem Programm eine beliebige Dezimalzahl in einen Bruch umwandeln. Kennt jemand fertigen Code, der so was kann? Oder kann mir da jemand in der Sache Vorgehensweise weiter helfen?

Re: Dezimalzahlen in Bruch umwandeln

Verfasst: 14.11.2011 22:46
von STARGÅTE
Vorgehensweise:

Dezimalzahl in 10er, 100er ... Bruch und dann Kürzen:

0,0625 -> 625/10000 -> 1/16

Code: Alles auswählen

; Struktur eines Bruchs
Structure Fraction
	Numerator.i
	Denominator.i
EndStructure

; Erstellt einen Bruch aus einer Fließkommazahl.
Procedure DecimalFraction(*Fraction.Fraction, Float.f)
	Protected Factor.i = 1
	While Int(Float)*1.0 <> Float
		Float * 10
		Factor * 10
	Wend
	*Fraction\Numerator = Float
	*Fraction\Denominator = Factor
EndProcedure

; Kürzt einen Bruch so weit wie es möglich ist.
Procedure SimplifyFraction(*Fraction.Fraction)
	Protected Mod.i
	Protected Numerator.i = *Fraction\Numerator
	Protected Denominator.i = *Fraction\Denominator
	Repeat
		Mod = Numerator % Denominator
		If Mod
			Numerator = Denominator
			Denominator = Mod
		EndIf
	Until Mod = 0
	*Fraction\Numerator / Denominator
	*Fraction\Denominator / Denominator
EndProcedure

; Gibt einen Bruch als Zeichenkette zurück.
Procedure.s ExportFraction(*Fraction.Fraction)
	ProcedureReturn Str(*Fraction\Numerator)+"/"+Str(*Fraction\Denominator)
EndProcedure


;## Beispiel

DecimalFraction(A.Fraction, 0.0625)
Debug ExportFraction(A)
SimplifyFraction(A)
Debug ExportFraction(A)
Hinweis: Problematisch wird es nur, wenn die Float nicht "richtig" dargestellt werden kann (also 0.02 ist 0.01999...), dann müsste man ggf zu Doubles wechseln.

Re: Dezimalzahlen in Bruch umwandeln

Verfasst: 14.11.2011 23:28
von helpy
STARGÅTE hat geschrieben:Hinweis: Problematisch wird es nur, wenn die Float nicht "richtig" dargestellt werden kann (also 0.02 ist 0.01999...), dann müsste man ggf zu Doubles wechseln.
Oder Man verwendet den String, verschiebt das Komma um x Stellen, nimmt als Nenner 10^X und kürzt dann.

;-)

lg,
guido

Re: Dezimalzahlen in Bruch umwandeln

Verfasst: 15.11.2011 03:25
von CSHW89
Ich hatte mal dazu eine kleine Procedure geschrieben, die nicht auf dem 10er-System basiert, sondern auf dem 2er-System (d.h. der Nenner ist eine 2er-Potenz). Hier mal der Code:

Code: Alles auswählen

Procedure Rational(double.d)
  Protected num.q, den.q, add.q, pow.d, i.i, sgn.i
  
  sgn = 1
  If (double < 0)
    double * -1
    sgn = -1
  EndIf
  den = 1
  pow = 1
  k = 0
  While (double > pow)
    pow * 2
    k + 1
  Wend
  i = 61
  Repeat
    pow / 2
    add = 1 << i
    If (k = 0)
      den + add
    Else: k - 1
    EndIf
    If (double => pow)
      double - pow
      num + add
    EndIf
    i - 1
  Until (i = -1)
  num * sgn
  
  Debug num
  Debug den
  Debug StrD(num/den)
EndProcedure

Rational(0.2)
Weiß jetzt grad nicht mehr ganz so genau, wie der funktioniert ^^, aber er tut, was er verspricht.

lg Kevin

Re: Dezimalzahlen in Bruch umwandeln

Verfasst: 15.11.2011 06:11
von NicTheQuick
CSHW89 hat geschrieben:Weiß jetzt grad nicht mehr ganz so genau, wie der funktioniert ^^, aber er tut, was er verspricht.
Bei mir kommt bei deinem Beispiel das hier raus:
Debugger hat geschrieben:922337203685477632
4611686018427387904
0.2000000000
Wenn man das durcheinander teilt, ergibt das zwar ungefähr 0.2, aber schön ist das nicht. Das exakte Ergebnis deines Bruchs wäre übrigens 0.200000000000000011102230246251565404236316680908203125
Außerdem wäre das richtig gekürzt: 3602879701896397/18014398509481984

Re: Dezimalzahlen in Bruch umwandeln

Verfasst: 15.11.2011 10:44
von marl
Super, erst mal allen herzlichen Dank für die schnellen Antworten.

Stargate, der Code ist toll, er berücksichtigt allerdings nicht die periodischen Zahlen, also sowas wie o,33333... oder 0,252525
Hier müsste man von der Berechnung her anders vorgehen. Das könnte ich selbst machen,
ich habe jetzt aber keinen Plan, wie mein Programm so eine periodische Zahl erkennen könnte!?

Re: Dezimalzahlen in Bruch umwandeln

Verfasst: 15.11.2011 13:35
von STARGÅTE
Wenn du 0.3333 gegeben hast, kann das Programm unmöglich entscheiden, ob du 1/3 meinst, oder wirklich in dem fall 3333/10000.

Das heißt du musst zumindest irgendwie kenntlich machen, ob es sich tatsächlich um eine Periode handelt und ab wann sie beginnt.

Wenn du das dann weißt, kannst du es ähnlich wie mit dem 10er, 100er ... Bruch mit einem 9er, 99er, 999er Bruch machen.

Beispiel:
0.3 = 3/9 = 1/3
0.83 = 8.3 : 10 = 8/10 + 3/90 = 8/10 + 1/30 = 25/30 = 5/6

Weiterführende Infos gibs hier: Dezimalsystem

Re: Dezimalzahlen in Bruch umwandeln

Verfasst: 15.11.2011 13:38
von CSHW89
NicTheQuick hat geschrieben:
CSHW89 hat geschrieben:Weiß jetzt grad nicht mehr ganz so genau, wie der funktioniert ^^, aber er tut, was er verspricht.
Bei mir kommt bei deinem Beispiel das hier raus:
Debugger hat geschrieben:922337203685477632
4611686018427387904
0.2000000000
Wenn man das durcheinander teilt, ergibt das zwar ungefähr 0.2, aber schön ist das nicht. Das exakte Ergebnis deines Bruchs wäre übrigens 0.200000000000000011102230246251565404236316680908203125
Außerdem wäre das richtig gekürzt: 3602879701896397/18014398509481984
Joa stimmt schon. Erstens ist der Code schon Jahre alt, zweitens ist das halt die Natur der Gleitkommazahlen, dass sie nicht genau 0.2 speichern können, und drittens wegen dem Kürzen kannste ja nochmal Euklid drüber jagen ;).
Gibt aber mit Sicherheit bessere Algorithmen.

lg Kevin

Re: Dezimalzahlen in Bruch umwandeln

Verfasst: 15.11.2011 13:44
von marl
Danke Stargate für die Info. Mein Problem ist ja jetzt auch, wie man an einer Zahl erkennt, daß es sich um eine periodische handelt!

Re: Dezimalzahlen in Bruch umwandeln

Verfasst: 15.11.2011 14:04
von STARGÅTE
Das habe ich doch angedeutet: Du kannst es nicht erkennen, wenn es nicht "markiert" ist.

Mathematisch mit einem Überstrich über der Periode.
Wenn man keine stilistischen Mittel nutzen kann (wie hier in PB), kann man eine _ oder ¯ voran stellen.