Autor |
Beitrag |
F34r0fTh3D4rk
      
Beiträge: 5284
Erhaltene Danke: 27
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: So 27.11.05 10:40
Ich schreibe gerade eine Funktion, um Fließkommazahlen in Brüche umzuwandeln, für meine unit UBruchrechnung, soweit hab ichs jetzt:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| procedure TForm1.Button6Click(Sender: TObject); var Bruch: TBruch; nc, i: integer; flt: extended; str: string; begin flt := strtofloat(edit5.text); nc := 1; for i := 1 to length(inttostr(round(frac(flt)))) do nc := nc * 10; Bruch.Zaehler := round(flt * nc); Bruch.Nenner := nc;
Bruch := p_kuerzen(Bruch); Label1.Caption := inttostr(Bruch.Zaehler); Label2.Caption := inttostr(Bruch.Nenner); end; |
Ganz Perfekt ist es noch nicht, auch hab ich noch so die bedenken, wie ich das mit periodischen Zahlen mache, aber ich denke, selbst an dieser Funktion lässt sich schon ne Menge Verbessern, ich hoffe mal, dass strings nicht sein müssen.
Aus 6/7 macht er:
0,857142857142857
und daraus macht er wieder 9/10
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| function BruchToFloat(Bruch: TBruch): Extended; begin result := Bruch.Zaehler / Bruch.Nenner; end;
procedure TForm1.Button7Click(Sender: TObject); var Bruch: TBruch; begin Bruch.Zaehler := strtoint(edit1.text); Bruch.Nenner := strtoint(edit2.text); edit5.Text := floattostr(BruchToFloat(Bruch)); end; |
(warum eigentlich nur 15 nachkommastellen ?)
Die unit die man zum kürzen und für die Brüche braucht gibts hier:
www.delphi-library.d...ewtopic.php?p=313675
Danke schonmal  Das fertige Ergebnis kommt dann in die Unit rein.
|
|
Lannes
      
Beiträge: 2352
Erhaltene Danke: 4
Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
|
Verfasst: So 27.11.05 12:49
Hallo,
F34r0fTh3D4rk hat folgendes geschrieben: | ...(warum eigentlich nur 15 nachkommastellen ?) |
FloatToStr berücksichtigt nur 15 Stellen, hier die Alternativen bis 18 Stellen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure TForm1.Button7Click(Sender: TObject); var Bruch: TBruch; begin Bruch.Zaehler := strtoint(edit1.text); Bruch.Nenner := strtoint(edit2.text); edit5.Text := Format('%.18f',[BruchToFloat(Bruch)]); end; |
_________________ MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
|
|
F34r0fTh3D4rk 
      
Beiträge: 5284
Erhaltene Danke: 27
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: So 27.11.05 13:03
dachte ich mir, nur muss ich diese funktion hier irgendwie mal anständig optimieren: Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| procedure TForm1.Button6Click(Sender: TObject); var Bruch: TBruch; nc, i: integer; flt: extended; str: string; begin flt := strtofloat(edit5.text); nc := 1; for i := 1 to length(inttostr(round(frac(flt)))) do nc := nc * 10; Bruch.Zaehler := round(flt * nc); Bruch.Nenner := nc;
Bruch := p_kuerzen(Bruch); Label1.Caption := inttostr(Bruch.Zaehler); Label2.Caption := inttostr(Bruch.Nenner); end; |
ich will möglichst die string umwandlungen und am besten noch frac da raus haben, nur wie ?
Aus 1,587 macht er 8/5 aus 8/5 aber 1,6
ohne runden stimmts jetzt:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| procedure TForm1.Button6Click(Sender: TObject); var Bruch: TBruch; nc, i: integer; flt: extended; begin flt := strtofloat(edit5.text); nc := 1; for i := 1 to length(floattostr(frac(flt))) do nc := nc * 10; Bruch.Zaehler := round(flt * nc); Bruch.Nenner := nc;
Bruch := p_kuerzen(Bruch); Label1.Caption := inttostr(Bruch.Zaehler); Label2.Caption := inttostr(Bruch.Nenner); end; |
Fehler von mir, sry, nur muss man die nachkommastellen doch auch irgendwie anders herausbekommen, nur wie ?
|
|
F34r0fTh3D4rk 
      
Beiträge: 5284
Erhaltene Danke: 27
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: So 27.11.05 14:44
nochmal den relevanten teil als funktionen:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51:
| type TBruch = record Zaehler, Nenner: integer; end;
function p_ggT(a, b: integer): integer; var x, y, r: Integer; begin x := a; y := b; r := x mod y; while (r <> 0) do begin x := y; y := r; r := x mod y; end; result := y; end;
function p_kuerzen(Bruch: TBruch): TBruch; var ggt: integer; begin result := Bruch; ggt := p_ggt(Bruch.Zaehler, Bruch.Nenner); if ggt = 1 then exit; result.Zaehler := Bruch.Zaehler div ggt; result.Nenner := Bruch.Nenner div ggt; end;
function BruchToFloat(Bruch: TBruch): Extended; begin result := Bruch.Zaehler / Bruch.Nenner; end;
function FloatToBruch(a: Extended): TBruch; var Faktor, i: integer; begin result.Nenner := 0; result.Zaehler := 0; Faktor := 1; for i := 1 to length(floattostr(frac(a))) do Faktor := Faktor * 10; result.Zaehler := round(a * Faktor); result.Nenner := Faktor; result := p_kuerzen(result); end; |
die markierten teile stören mich noch und die schleife müsste auch nicht unbedingt sein
ich könnte auch einfach maxint als faktor nehmen, aber das macht die funktion bissl langsam denke ich. hm geht ja net, dann übersteige ich maxint, so ein dreck, wenn ich dann aber int64 nehmen, bekomme ich so kein maximum
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| function FloatToBruch(a: Extended): TBruch; begin result.Nenner := 0; result.Zaehler := 0; result.Zaehler := round(a * 1000000000); result.Nenner := 1000000000; result := p_kuerzen(result); end; |
bei zahlen die ein wenig größer sind gibts dann probleme  das muss doch irgendwie zu lösen sein 
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: So 27.11.05 16:15
Zum zurückwandeln von Brüchen aus deren Dezimaldarstellung nimmt man meist die Kettenbruch-Zerlegung mit Hilfe des euklidischen Algos.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| I := 0; While Frac(X) > epsilon Do Begin K[I] := Trunc(X); X := 1 / Frac(X); Inc(I); end;
Z := Trunc(X); N := 1;
While I > 0 do Begin Tmp := N; N := Z; Z := Tmp;
Dec(I); N := N + K[I] * Z; end; |
Ungetestet ...
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
F34r0fTh3D4rk 
      
Beiträge: 5284
Erhaltene Danke: 27
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: So 27.11.05 16:35
ist das schneller, als eine umwandlung in einen string ?
was ist epsilon und muss der bruch danach noch gekürzt werden ?
|
|
DaRkFiRe
      
Beiträge: 526
WinXP Home & Professional
C, C++, Delphi
|
Verfasst: Mo 28.11.05 23:20
Epsilon ist eine Art Toleranzgrenze, die Du vorgibst.
_________________ Lang ist der Weg durch Lehren - kurz und wirksam durch Beispiele! Seneca
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mo 28.11.05 23:29
Je nach Wahl des Epsilons (Toleranzgrenze, normalerweise <1E-10) wirst Du eine Bruch-Annäherung machen müssen, d.h. dass er Dir den gekürzten Bruch
1000\3001 zurückgibt, obwohl Du 1/3 erwartest. Diese annäherung ist aber relativ einfach zu bewerkstelligen, da du einfach beim Zurückmultiplizieren nicht alle Glieder berücksichtigst.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
F34r0fTh3D4rk 
      
Beiträge: 5284
Erhaltene Danke: 27
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Di 29.11.05 14:07
dann ist es aber nicht so genau wie meins  und vielleicht auch langsamer 
|
|
Horst_H
      
Beiträge: 1654
Erhaltene Danke: 244
WIN10,PuppyLinux
FreePascal,Lazarus
|
Verfasst: Di 29.11.05 14:56
Hallo,
auch die Umwandlung in einen String hat keine unendliche Genauigkeit und kostet auch gewaltig Zeit.
Wandel mal 3.14159265.. um.
Der Kettenbruch liefert schon frueh 355/113 auch ohne GGT-bestimmung
Gruss Horst
|
|
F34r0fTh3D4rk 
      
Beiträge: 5284
Erhaltene Danke: 27
Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
|
Verfasst: Di 29.11.05 16:03
wie muss epsilon denn gewählt sein, um die richtigen brüche rauszubekommen ?
lässt sich die anzahl der nachkommastellen irgendwie anders bestimmen ?
|
|
|