![]() |
Re: Zahl als Bruch speichern
Hallo alzaimar,
Wie kommst du zu dem Schluss? GGT, KGV und auch REG sollen auch von aussen zur Verfügung stehen. Ich kann mir schon vorstellen dass man GGT und KGV und reg (kürzen) auch noch für andere Zwecke brauchen kann (Primzahlenberechnung oder ähnliches). Im übrigen hab ich vergessen bei der Division und Multiplikation zu kürzen (reg). Wer die Unit benützt bitte nachtragen. Grüsse Rainer |
Re: Zahl als Bruch speichern
Hallo,
hab das Kürzen bei mul und div eingebaut! Grüsse Rainer |
Re: Zahl als Bruch speichern
Zitat:
Die Funktion 'Kürzen' wird nun wirklich nicht außerhalb benötigt, da Du das ja nach jeder Operation ohnehin durchführst. |
Re: Zahl als Bruch speichern
Hallo alzaimar,
jetzt versteh ich! Im Allgemeinen hast du recht. Man sollte KGV und GGT aus der Klasse Tbruch nehmen und als unabhängige Prozeduren deklarieren. Grüsse Rainer |
Re: Zahl als Bruch speichern
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
hier nocheinmal der korrigierte und verbesserte Code:
Delphi-Quellcode:
Grüsse
unit U_bruchrechnen;
interface Type Bruchtyp=packed record z,n: int64; // Int64 bei sehr großen Zahlen end; TBruch = class(TObject) function red(b0,b1:int64):Bruchtyp; function add(b0,b1: Bruchtyp):Bruchtyp; function sub(b0,b1: Bruchtyp):Bruchtyp; function mul(b0,b1: Bruchtyp):Bruchtyp; function divide(b0,b1: Bruchtyp):Bruchtyp; end; function kgv(b0,b1:int64):int64; function ggt(b0,b1:int64):int64; implementation function kgv(b0,b1:int64):int64; Begin result:=b0*b1 div ggt(b0,b1); End; function ggt(b0,b1:int64):int64; var a,b,r:integer; Begin If b0>b1 then Begin a:=b0; b:=b1 end else begin b:=b0; a:=b1; end; // Berechnung des ggt repeat r:= a mod b; a:=b; b:=r until (r=0); result:=a; End; function TBruch.add(b0,b1: Bruchtyp):Bruchtyp; var a:integer;b:bruchtyp; Begin a:=kgv(b0.n,b1.n); b.n:=a; b.z:=(a div b0.n)*b0.z+(a div b1.n)*b1.z; result:=red(b.z,b.n); End; function TBruch.sub(b0,b1: Bruchtyp):Bruchtyp; var a:integer;b:bruchtyp; Begin a:=kgv(b0.n,b1.n); b.n:=a; b.z:=(a div b0.n)*b0.z-(a div b1.n)*b1.z; result:=red(b.z,b.n); End; function TBruch.mul(b0,b1: Bruchtyp):Bruchtyp; Begin result:=red(b0.z*b1.z,b0.n*b1.n); End; function TBruch.divide(b0,b1: Bruchtyp):Bruchtyp; // div geht nicht, weil das ja ein geschützter begriff ist... Begin result:=red(b0.z*b1.n,b0.n*b1.z); End; function TBruch.red(b0,b1:int64):Bruchtyp; var a,a0,a1:integer; Begin a0:=b0;a1:=b1; while ggt(a0,a1)<>1 do Begin a:=ggt(a0,a1); a0:=a0 div a; a1:=a1 div a; End; result.z:=a0; result.n:=a1; End; end. Rainer PS: Bevor die nächsten meckern; man kann GGT und KGV natürlich auch in eine andere Unit packen. Hat mit Bruchrechnung nur mittelbar was zu tun. |
Re: Zahl als Bruch speichern
@ws1976
Ich schlage folgende Änderungen vor In der Funktion ggt sollten die lokalen Variablen den Typ Int64 haben. Warum?: Weils sonst falsche Ergebnisse bringt, wenn nur einer der Parameter > maxint ist. in der Funktion kgv sollte nicht stehen result:=b0*b1 div ggt(b0,b1); sondern result:=b0 div ggt(b0,b1) * b1; Warum?: Weils sonst falsche Ergebnisse gibt, wenn b0*b1 > High(int64) ist. Das ist zwar auch bei der geänderten Variante nicht ausgeschlossen, tritt aber erst bei deutlich höheren Werten auf. |
Re: Zahl als Bruch speichern
Bist Du dir sicher, das a*b div c identisch mit (b div c)*a ist?
Beispiel : a=3, b=4, c=3. (a*b) div c a*b = 12 div 3 = 4 (b div c)*a 4 div 3 = 1 * 3 = 3 |
Re: Zahl als Bruch speichern
Zitat:
Nein, im Gegenteil. Ich bin mir, so wie auch du, sicher daß "a*b div c" nicht identisch ist mit "b div c * a", und ich bin auch sicher daß die Konstrukte i.d.R. unterschiedliche Resultate bringen. Ich bin mir aber sehr sicher, daß die Konstrukte identische Ergebnisse bringen, wenn c ein "GGT" von a und b ist, und das ist bei dem diskutierten Code der Fall. Der Vorteil der letztgenannten Konstruktion ist, daß sie höhere Werte verarbeiten kann. Stell dir vor a und b seien beide 9999999999 (also > maxint), dann wird bei der vorgeschalteten Multiplikation ein Zahlenüberlauf stattfinden, bei der nachgeschalteten Multiplikation aber nur dann, wenn das Gesamtergebnis > High(Int64) wird. Somit dürfte diese Konstruktion zuverlässiger arbeiten. |
Re: Zahl als Bruch speichern
mh... im Grunde habt ihr recht. Beachtet aber bitte, das c hier der ggt von a und b ist:
/ entspicht div a = 6 b = 4 c = ggt(6,4) = 2 (a x b) / c = (6 x 4) / 2 = 24 / 2 = 12 a x (b / c) = 6 x (4 / 2) = 6 x 2 = 12 b x (a / c) = 4 x (6 / 2) = 4 x 3 = 12 in diesem speziellen Fall entspricht (a x b) / c auch a x (b / c) und b x (a / c) Edit: Das kommt davon, wenn man früh morgens nur den halben letzten Beitrag liest... :duck: Edit2: Bei negativen Bruchzahlen kommts unweigerlich zum Crash. GGT darf nur Absolutwerte annehmen! |
Re: Zahl als Bruch speichern
Zitat:
Ich sehe im Moment keinen Grund, warum die von ws1976 vorgestellte GGT-Version Probleme mit negativen Zahlen haben sollte. |
Re: Zahl als Bruch speichern
Naja... ich geb zu ich hab es in C# 1:1 umgesetzt... beim Addieren eines Bruchs (-4/3) mit (1/3) hat es eine DivByZero Exception gehagelt. Beheben konnt ich das erst als ich die absoluten Werte für die GGT-Berechnung genommen hab.
:drunken: Die Sprachen mögen verschieden sein, aber die Arithmetik bleibt doch gleich... will ich zumindest meinen |
Re: Zahl als Bruch speichern
Warum sollte ich überhaupt eine Klasse dafür nehmen? Der Typ für den Bruch als Record und die entsprechenden Funktionen in einer Unit, sind für diesen Zweck vollkommen ausreichend.
Meiner Meinung nach ist eine Klasse sinnvoll, wenn Werte und Methoden damit zusammengeführt werden können, was hier nicht der Fall ist. Die Klasse TBruch ist nur eine Sammlung von Methoden, die ich wie o.g. verwalten kann. |
Re: Zahl als Bruch speichern
Zitat:
|
Re: Zahl als Bruch speichern
Zitat:
Jedenfalls bei mir arbeitet die GGT-Routine fehlerfrei, auch mit negativen Zahlen. |
Re: Zahl als Bruch speichern
bei mir klappts JETZT auch fehlerfrei... aber wenn ihr drüberschaun wollt, kann ich ja die .cs hier mit anhängen ;)
|
Re: Zahl als Bruch speichern
Liste der Anhänge anzeigen (Anzahl: 1)
Dann will ich hier auch mal meine Version der Unit veröffnetlichen :mrgreen:
Das ganze baut auf einen erweiterten Record-Datentyp auf, ist also erst ab Delphi 2006 verfügbar. Das besondere sind die class Operatoren, welche eine einfache Handhabung der Variablen zur Verfügung stellen. Die einzelnen Instanzen müssen nicht zuerst mit Create erstellt und mit Free freigegeben werden! Beispiel:
Delphi-Quellcode:
procedure foo;
var A, B, C: TBruch; begin A := 3; // jetzt steht in A 3/1 B.Zaehler := 8; B.Nenner := 5; // jetzt steht in B 8/5 B := B + 1; // jetzt steht in B 13/5 C := B * A; // (13/5) * (3/1) = 39/5 C := C / 13; // C = 3/5 showmessage(FloatToStr(C)); // Fließkommazahl! 0,6 end; |
Re: Zahl als Bruch speichern
Liste der Anhänge anzeigen (Anzahl: 1)
ähnlich wie meins ;)
C# mit .NET 2 notwendig ein wenig anglifiziert das ganze... |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:45 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz