AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

die Division eines Taschenrechners

Ein Thema von Kanikkl · begonnen am 11. Okt 2009 · letzter Beitrag vom 11. Okt 2009
Antwort Antwort
Kanikkl

Registriert seit: 11. Okt 2009
Ort: Soest
10 Beiträge
 
#1

die Division eines Taschenrechners

  Alt 11. Okt 2009, 13:19
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:
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;
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.

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?
  Mit Zitat antworten Zitat
Benutzerbild von patti
patti

Registriert seit: 20. Okt 2004
Ort: Mittelfranken
665 Beiträge
 
Turbo Delphi für Win32
 
#2

Re: die Division eines Taschenrechners

  Alt 11. Okt 2009, 13:23
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.
Patrick Kreutzer
[Informatik-Student im 4. Semester]
http://www.patti-k.de/
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.540 Beiträge
 
Delphi 11 Alexandria
 
#3

Re: die Division eines Taschenrechners

  Alt 11. Okt 2009, 13:30
Wozu soll die Zeile
Zitat:
ergebnis:=ergebnis+0.000001;
innerhalb der Schleife eigentlich gut sein?

[edit] Und wäre eine Kopfschleife nicht angebrachter? [/edit]
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Kanikkl

Registriert seit: 11. Okt 2009
Ort: Soest
10 Beiträge
 
#4

Re: die Division eines Taschenrechners

  Alt 11. Okt 2009, 13:46
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:

ergebnis:=ergebnis+0.000001; 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.


Hoffe ich konnte dir meine Idee plausibel erklären Wenn nicht, schlag mich ^^
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.540 Beiträge
 
Delphi 11 Alexandria
 
#5

Re: die Division eines Taschenrechners

  Alt 11. Okt 2009, 16:19
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:
function krechnungen.dividieren(x,y: extended): extended;
begin
  Result := 0;
  while x > y do
    begin
      Result := Result + 1;
      x := x - y;
    end;
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.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Kanikkl

Registriert seit: 11. Okt 2009
Ort: Soest
10 Beiträge
 
#6

Re: die Division eines Taschenrechners

  Alt 11. Okt 2009, 17:06
der Nachkommanteil ist ja das was mir SOrgen bereitet =S
  Mit Zitat antworten Zitat
Benutzerbild von alleinherrscher
alleinherrscher

Registriert seit: 8. Jul 2004
Ort: Aachen
797 Beiträge
 
Delphi XE2 Professional
 
#7

Re: die Division eines Taschenrechners

  Alt 11. Okt 2009, 17:23
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:
TDezimalstelle=0..9
TZahl=record
   Vorkomma:int64;
   Nachkomma:array of TDezimalstelle
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

Also:

Delphi-Quellcode:

 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;
Und nochwas:

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))
„Software wird schneller langsamer als Hardware schneller wird. “ (Niklaus Wirth, 1995)

Mein Netzwerktool: Lan.FS
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:14 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz