Dezimalzahlen in Bruch umwandeln

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
NicknameFJ
Beiträge: 324
Registriert: 03.06.2007 14:36
Wohnort: Von der Sonne aus gesehen der dritte Planet

Re: Dezimalzahlen in Bruch umwandeln

Beitrag von NicknameFJ »

marl hat geschrieben:Ja das ist klar. Bei meiner Anwendung wird die Zahl allerdings nicht von einem Benutzer eingegeben, sondern errechnet. Ich muss also mit einer mathematischen Methode die Periode erkennen.
Wenn Du die Zahl im Programm doch erst berechnest, dann kennst Du doch schon Zähler und Nenner der Divison. Oder was sehe ich das falsch?

NicknameFJ


[EDIT]
Errechne den Kehrwert deiner Bruchzahl.
Jetzt lässt Du eine Schleife mit Laufvariablen x laufen von sagen wir 2 bis 100000000 (beliebig).
Multipliziere die Laufvariable mit dem oben errechneten Kehrwert. Sobald bei der Multiplikation eine Ganzzahl rauskommt hast Du den Nenner (= das errechnete Produkt aus Kehrwert und Laufvar.)

Brauchst nicht mal den Kehrwert, kannste auch mit Deiner Bruchzahl, dann hast Du sogar direkt den Zähler und den Nenner. Die Genauigkeit ergibt sich durch die Größe des Schleifenendes

[ENDEDIT]
Zuletzt geändert von NicknameFJ am 15.11.2011 19:56, insgesamt 1-mal geändert.
PS: Alle im Text enthaltenen Schreibfehler sind beabsichtigt und dienen der Belustigung aller

Bild
marl
Beiträge: 13
Registriert: 05.02.2009 17:55
Kontaktdaten:

Re: Dezimalzahlen in Bruch umwandeln

Beitrag von marl »

aber du glaubst es ja scheinbar immer noch nicht.
sorry, das letzte was ich will, ist hier als Ungläubiger da zu stehen.
Natürlich bleibt 0,333 immer 0,333! Ich habe nicht behauptet, daß das eine Periode sei.
Die Zahl die ich in einen Bruch umwandeln will wird errechnet und ich möchte wissen, ob es eine Periode ist oder nicht, damit ich dann die Umwandlung richtig vornehmen kann.

Wenn es dazu keine mathematische Methode gibt, dann soll es so sein.

Ich frage mich nur wie die Programmierer von Excel das machen. Wenn ich hier z.B. 0,33 eingebe und als Bruch "formatiere", dann steht da 1/3 und nicht 33/100!
---------------------------------------------
PB 4.2 und 4.5 WIN XP / WIN 7
Benutzeravatar
gnasen
Beiträge: 578
Registriert: 01.08.2007 14:28
Computerausstattung: PB 4.60

Re: Dezimalzahlen in Bruch umwandeln

Beitrag von gnasen »

hmm der Punkt ist folgender: Geht es dir um eine ungefähre Näherung, so lässt sich soetwas schnell erzielen (ich habs jetzt nicht ausprobiert, aber ich denke Stargates Code kann das).
Möchtest du allerdings exakt sein, ohne Rundungsfehler, dann ist die Rückrechnung schlichtweg nicht in der Form möglich wie du sie gerne hättest.
Wenn du "nur" triviale Rechenoperationen ala +-*/ nutzt, kann man das ganze selbst übernehmen, die Notation des periodischen Anteils etc, aber der Rechenaufwand ist mitunter sehr groß. Und auch der Aufwand das ganze zu programmieren ist nicht ohne. Und ein paar Kentnisse in elementarer Zahlentheorie wären dann natürlich auch nicht ganz verkeht.

Musst du dir gut überlegen, ob der Nutzen den Aufwand lohnt
pb 4.51
marl
Beiträge: 13
Registriert: 05.02.2009 17:55
Kontaktdaten:

Re: Dezimalzahlen in Bruch umwandeln

Beitrag von marl »

Danke gnasen für die Rückmeldung. Bei der Genauigkeit kann ich durchaus Abstriche machen kann. Ich werds mit dem Code von Stargate (nochmals Danke für die prompte Antwort) probieren, der hilft mir, denke ich, sehr weiter.
---------------------------------------------
PB 4.2 und 4.5 WIN XP / WIN 7
marl
Beiträge: 13
Registriert: 05.02.2009 17:55
Kontaktdaten:

Re: Dezimalzahlen in Bruch umwandeln

Beitrag von marl »

hm, im Grunde genommen NicknameFJ hast du da recht. Ich werde es mir mal durch den Kopf gehen lassen!
---------------------------------------------
PB 4.2 und 4.5 WIN XP / WIN 7
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Dezimalzahlen in Bruch umwandeln

Beitrag von STARGÅTE »

marl hat geschrieben:Ich frage mich nur wie die Programmierer von Excel das machen. Wenn ich hier z.B. 0,33 eingebe und als Bruch "formatiere", dann steht da 1/3 und nicht 33/100!
:lol: , ja super, vermutlich weil du dort angegeben hast, dass der Bruch-Typ Einstellig ist :lol:

Wie du siehst, sind also zwangsweise mehr Informationen nötig, damit das Programm weiß, in welche Richtung es gehen soll.
Dann macht Excel vermutlich das gleiche, was ich versucht habe im letzten Post anzudeuten, dass es den Nenner variiert, bis der Bruch "schöner" gekürzt wird.

Oder Excel berechnet vorab alle möglichen Brüche: also 1/2, 1/3, 1/4, 1/5, ... 2/9, .. 3/5 usw. und vergleich die Dezimalzahlen jeweils mit dem eingegebenen Wert.
Der der am nähsten dran ist, ist der Bruch.

Das sieht dann so aus:

Code: Alles auswählen

Procedure.s GetFraction(Float.f, Level.i)
	Protected N.i, M.i, Difference.f
	Protected NN.i, MM.i
	Protected MinDifference.f = Infinity()
	For N = 1 To Level
		For M = 1 To N
			Difference = Abs(Float-M/N)
			If Difference < MinDifference
				MinDifference = Difference
				NN = N
				MM = M
			EndIf
		Next
	Next
	ProcedureReturn Str(MM)+"/"+Str(NN)
EndProcedure

Debug GetFraction(0.5, 9)
Debug GetFraction(0.33, 9)
Debug GetFraction(0.55, 9)
Debug GetFraction(0.66, 9)

Debug GetFraction(0.1818, 99)
Debug GetFraction(0.230769, 99)
Edit: Code ist nicht mit Abbruchbedingungen optimiert!

Level gibt halt an, wie groß der Nenner maximal sein soll.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: Dezimalzahlen in Bruch umwandeln

Beitrag von Nino »

marl hat geschrieben:Ich frage mich nur wie die Programmierer von Excel das machen. Wenn ich hier z.B. 0,33 eingebe und als Bruch "formatiere", dann steht da 1/3 und nicht 33/100!
Evtl. haben sie da eine Heuristik eingebaut etwa in der Art:
Wenn die selbe Ziffer oder Zifferngruppe nach dem Komma am Ende der Zahl x-mal oder öfter vorkommt, dann hat derjenige, der die Zahl geschrieben hat, damit wohl ein periodisches Auftreten ausdrücken wollen.
Wenn dann (etwa in den Optionen) ein Wert für x festgelegt ist, lässt sich die gewünschte Umwandlung leicht durchführen. Es kann sein, dass das tatsächlich das Verhalten ist, welches manche oder viele Benutzer erwarten. Das ändert allerdings nichts daran, dass solch ein Ergebnis auf einer puren Annahme beruht und mathematisch falsch ist. Denn wenn jemand 0,33 eingibt und auch exakt diesen Wert meint, dann ist das eben nicht 1/3. 0,33 kann nunmal nicht gleichzeitig 1/3 und 33/100 bedeuten.
marl
Beiträge: 13
Registriert: 05.02.2009 17:55
Kontaktdaten:

Re: Dezimalzahlen in Bruch umwandeln

Beitrag von marl »

ja, stargate, genau so ist es wohl. Ich habs begriffen, hilft und reicht von der Genauigkeit für meine Applikation auch aus.
Danke!
---------------------------------------------
PB 4.2 und 4.5 WIN XP / WIN 7
Benutzeravatar
helpy
Beiträge: 636
Registriert: 29.08.2004 13:29

Re: Dezimalzahlen in Bruch umwandeln

Beitrag von helpy »

Nino hat geschrieben:Evtl. haben sie da eine Heuristik eingebaut etwa in der Art:
Viel einfacher! Excel rundet!

Excel bietet bei der Zellformatierung die Möglichkeit eine Zelle als Bruch darzustellen. Als Option kann man auswählen wie Excel rundet. Je nach Einstellung zeigt Excel für 0,33 folgende Brüche an:
Einstellig (1/4) ==> 1/3
Zweistellig (21/25) ==> 1/3
Dreistellig (312/943) ==> 33/100
Als Halbe (1/2) ==> 1/2
Als Viertel (2/4) ==> 1/4
Als Achtel (4/8) ==> 3/8
Als Sechzehntel (8/16) ==> 5/16
Als Zehntel (3/10) ==> 3/10
Als Hundertstel (30/100) ==> 33/100
lg,
guido
Windows 10
PB Last Final / (Sometimes testing Beta versions)
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Dezimalzahlen in Bruch umwandeln

Beitrag von STARGÅTE »

Aus aktuellem Anlass hier mal eine Prozedur die aus einer Dezimalzahl einen (den kleinstmöglichen) Bruch erzeugt,
welcher bis auf angegebenen relativen Fehler mit der Dezimalzahl übereinstimmt.
Wäre nett wenn der eine oder andere sie mal ein bisschen durchtestet.
Wer will, kann sich auch die Interationsschritt angucken.

Code: Alles auswählen

Procedure.s ToFraction(Double.d, MaxRelativeError.d=1e-6)
	
	Protected LowNumerator.q = 0,  LowDenominator.q = 1
	Protected HighNumerator.q = 1, HighDenominator.q = Round(1/Abs(Double), #PB_Round_Down)-1
	Protected Numerator.q   = LowNumerator  + HighNumerator
	Protected Denominator.q = HighNumerator + HighDenominator
	Protected Fraction.d=Infinity(), OldFraction.d
	Protected Factor.i, Iteration.i, Sign.s
	
	If Double < 0
		Double = Abs(Double)
		Sign = "-"
	EndIf
	If IsInfinity(Double) Or IsNAN(Double) Or Double > 1e16 Or Double < 1e-16 
		ProcedureReturn ""
	EndIf
	
	Repeat
		Iteration + 1
		OldFraction = Fraction
		Fraction = 1 - Double * Denominator / Numerator
		;Debug "Iteration "+RSet(Str(Iteration),3)+":  " + Str(Numerator) + " / " + Str(Denominator) + "   ( δ = "+Fraction+" )"
		Factor = Abs(Fraction) / (Abs(OldFraction)-Abs(Fraction))
		If Factor < 1 Or Fraction > 0 Or OldFraction > 0: Factor = 1 : EndIf
		If Fraction < -MaxRelativeError ; zu klein
			LowNumerator   = Numerator
			LowDenominator = Denominator
			Numerator   + Factor*HighNumerator
			Denominator + Factor*HighDenominator
		ElseIf Fraction > MaxRelativeError ; zu groß
			HighNumerator   = Numerator
			HighDenominator = Denominator
			Numerator   + Factor*LowNumerator
			Denominator + Factor*LowDenominator
		Else
			ProcedureReturn Sign + Str(Numerator) + "/" + Str(Denominator)
		EndIf
	ForEver
	
EndProcedure


Debug "Ein paar Brüche:"
Debug StrD(0.375) + " = " + ToFraction(0.375)
Debug StrD(0.3333333) + " = " + ToFraction(0.3333333)
Debug StrD(0.0625) + " = " + ToFraction(0.0625)
Debug StrD(-1.15) + " = " + ToFraction(-1.15)
Debug StrD(13.4) + " = " + ToFraction(13.4)
Debug "Näherungsbrüche der Kreiszahl:" ; https://de.wikipedia.org/wiki/Kreiszahl#Näherungsbrüche_der_Kreiszahl
Debug StrD(#PI) + " = " + ToFraction(#PI, 1e-3) + "   ("+StrD(22.0/7.0, 2)+")"
Debug StrD(#PI) + " = " + ToFraction(#PI, 1e-5) + "   ("+StrD(355.0/113.0, 4)+")"
Debug "Weitere Brüche:"
Debug ToFraction(127./307.)
Debug ToFraction(1018/717.0)
Debug ToFraction(-73/105.0)
Debug ToFraction(1.0/1000.0)
Debug ToFraction(7.0/10000.0)
Debug ToFraction(999.0/1000.0)
Debug ToFraction(9999.0/10000.0, 1e-8)
Debug ToFraction(499999.0/999999.0, 1e-12)
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Antworten