![]() |
die Division eines Taschenrechners
Ich glaube mittlerweile ist bekannt dass ich an nem Taschenrechner arbeite der aufeinander Aufbaut xD Und jetzt wird mir langsam klar, dass die division doch kein all zu leichtes Stück ist.
Mein Code sieht so aus:
Delphi-Quellcode:
und bei einer simplen division wie 2/2 bekomme ich einen Wert wie 1.0000000001 heraus. Ich vermute es hängt mit der until schleife zusammen, die rechnet ja noch einen weiteren Schritt und wird erst nach der letzten(+1) schleife angehalten. Dass heißt ein Schritt ist unnötigt.
function krechnungen.addieren(x,y: extended): extended;
begin result:=x+y; end; function krechnungen.subtrahieren(x,y: extended): extended; begin result:=x-y; end; function krechnungen.multiplizieren(x,y: extended): extended; var temp :extended; i, durchlauf: integer; begin temp:=x; durchlauf:=round(y); for i:=1 to durchlauf-1 do begin temp:=self.addieren(temp,x); end; result:=temp; end; function krechnungen.dividieren(x,y: extended): extended; var temp,ergebnis :extended; begin temp:=x; temp:=self.multiplizieren(temp,1000000); ergebnis:=0; repeat temp:=self.subtrahieren(temp,y); ergebnis:=ergebnis+0.000001; until (temp=0) or (temp<0) or (temp<y); result:=ergebnis; end; Wie bekomme ich es hin, dass die Methode diesen Schritt nicht ausführt? Ich bin mir nicht sicher, aber kann man da etwas mit einer While (temp>0) and (temp<y); schleife anfangen? Oder kann man den Mechanismus irgendwie simpler hinbekommen? |
Re: die Division eines Taschenrechners
Und warum benutzt du nicht einfach "*" bzw. "/" für Multiplikation/Division?
Patti Edit: Ah, ok. In deinem anderen Thread steht, dass du deinen Taschenrechner nur mit Hilfe von Addition und Subtraktion arbeiten lassen willst. |
Re: die Division eines Taschenrechners
Wozu soll die Zeile
Zitat:
[edit] Und wäre eine Kopfschleife nicht angebrachter? [/edit] |
Re: die Division eines Taschenrechners
damit kann möglichst genau gerundet werden.
z.b. hast du eine Zahl_x = 100 und eine Zahl_y = 11 durch die geteilt wird. Stell dir jetzt vor das Ergebnis von 100/11 sei 9,0909090909090909090909090909091. Dieses Ergebnis hat ganz ganz viele Nachkommastellen. Wenn du nun mit Hilfe der Subtraktion ermitteln willst, wie oft Zahl_y in Zahl_x hinein passt, benötigt man eine Schleife, die bei jedem Durchlauf eine Variable um 1 erhöht. Wenn man nun eine Schleife hat, in der 100-11 -> 89-11 -> 78-11 -> ... -> 12-11. So jetzt hat man einen Rest von 1, somit ist das Ergebnis keine ganze Zahl, sondern eine Periodische, da der Rest=1 ist. Dabei wurde die Schleife 9x wiederholt und das Ergebnis lautet 9. Meine Idee greift jetzt diesen Logarithmus auf, indem Zahl_x um i=100.000 erhöht wird und somit Zahl_y öfters in diese Zahl hinein passt und das Ergebnis gerundet wird, denn 100.000/11 = 9090, mit einem Rest von 10. Wenn man die Zahl jetzt wieder ins Verhältnis von 100:11 bringt, sollte normalerweise ein Ergebnis von 9,0909 heraus kommen. Und genau das macht diese Zeile:
Delphi-Quellcode:
Hier wird die erläuterte Idee aufgegriffen, denn wenn Zahl_x erhöht wird, ist das Ergebnis nicht mehr zur Eingabe des Benutzers Realistisch, somit muss anstatt von ergebnis+1; ergebnis+0.000001 gerechnet werden.
ergebnis:=ergebnis+0.000001;
Hoffe ich konnte dir meine Idee plausibel erklären :P Wenn nicht, schlag mich ^^ |
Re: die Division eines Taschenrechners
Aber wenn das Ergebnis eine ganze Zahl ist, stimmt es nach Deinem Schleifendurchlauf doch nicht, da ja in jedem Fall 0,000001 dazuaddiert werden. Ich fürchte, Du wirst da schon mit 2 Schleifen arbeiten müssen.
Delphi-Quellcode:
Somit hast Du zumindest schon den Vorkommaanteil. Sollte x > 0 sein, müsstest Du nun noch den Nachkommaanteil berechnen, ansonsten wärst Du fertig und das Ergebnis würde stimmen.
function krechnungen.dividieren(x,y: extended): extended;
begin Result := 0; while x > y do begin Result := Result + 1; x := x - y; end; |
Re: die Division eines Taschenrechners
der Nachkommanteil ist ja das was mir SOrgen bereitet =S
|
Re: die Division eines Taschenrechners
Darf ich an dieser Stelle anmerken, dass deine Multiplikation nicht korrekt ist, die funktion nur, wenn beide zahlen >1 sind und keine Kommastellen haben...
//edit: ah, aber nicht so richtig... da fehlt auch die nachkommabehandlung so ein bisschen: Beispiel: 0.1*5.5=0.6, was daran liegt dass du (um zu wissen, wie oft du die schleife durchlaufen musst) die variable durchlauf rundest. Zur Division Ich habe mir folgendes überlegt. Nehmen wir mal die Funktion von DeddyH und nennen sie nicht Dividieren sondern "SimpleDIV(x:integer,y:integer):integer" damit kannst du also gucken, wie oft quasi y in x reinpasst. So und den rest (also die kommastellen) berechnest du jetzt über die gute alte Schuldivision 10:8=1,25 ------ 20 -16 ------ 40 -40 ------ 0 Jetzt zur konkreten Umsetzung: Ich würde etwas elementarer anfangen. Definiere dir erstmal einen eigenen Zahlentyp z.B.
Delphi-Quellcode:
Damit kannst du auch wunderschön auf die einzelnen Nachkommastellen zugreifen. Denn ich hatte jetzt gerade das problem, dass ich bei der Division den Wert, den SimpleDIV liefert mit 0.1 multiplizieren wollte, um ihn an die erste Nachkommastelle zu bringen, was aber nicht so recht funktionieren wollte. So kannst du jetzt sachen Zahl.Nachkomma[1]= irgendwas
TDezimalstelle=0..9
TZahl=record Vorkomma:int64; Nachkomma:array of TDezimalstelle Also:
Delphi-Quellcode:
Und nochwas:const Stellen=10; type TDezimalStelle=0..9; TZahl=record Vorkomma:int64; Nachkomma:array of TDezimalStelle; end; {...} function SingleDIV(x,y:extended):integer; begin Result := 0; while x >= y do begin Result := Result + 1; x := x - y; end; end; function TZahlToExtended(Zahl:TZahl):extended; var i:integer; {hier habe ich mir erlaubt, mathematische Funktionen einzubauen, da diese Funktion ja zunächst nur der Darstellung von Zahlen dient und nicht der internen Berechnung...} begin result:=Zahl.Vorkomma; for i:=0 to Stellen do begin result:=result+(Zahl.Nachkomma[i] / (power(10,(i+1)))); end; end; function dividieren(x,y: extended): extended; var i,j:integer; Zahl : TZahl; begin //berechne x/y setlength(Zahl.Nachkomma,Stellen+1); Zahl.Vorkomma:=SingleDIV(x,y); for i:=1 to Zahl.Vorkomma do x:=Subtrahieren(x,y); for j:= 0 to Stellen do begin x:=multiplizieren(x,10); Zahl.Nachkomma[j]:=SingleDIV(x,y); For i:=1 to Zahl.Nachkomma[j] do x:=subtrahieren(x,y); end; result:=TZahlToExtended(Zahl); end; In der Mathematik führt man die Subtraktion durch die Addition ein: Also müsstest du, um es wirklich sauber zu machen sagen: subtraktion(x,y):= addition(x,-y) Selbes gilt für die Multiplikation (allerdings müsste man dann die division so umschreiben, dass sie keine Multiplikation mehr benutzt, sonst dreht man sich im Kreise)...aber das wäre ja durch eine kleine for schleife machbar. Multiplikation:=Division(x,Division(1,y)) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:59 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