AGB  ·  Datenschutz  ·  Impressum  







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

Genauigkeit von Datentypen

Ein Thema von PaddyVII · begonnen am 25. Feb 2015 · letzter Beitrag vom 26. Feb 2015
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von PaddyVII
PaddyVII

Registriert seit: 20. Nov 2014
Ort: Pforzheim
75 Beiträge
 
Delphi XE6 Enterprise
 
#1

Genauigkeit von Datentypen

  Alt 25. Feb 2015, 13:35
Guten Mittag, Delphianer,

ich denke ich hab hier etwas gefunden, über das nicht nur ich mir den Kopf zerbreche, aber ich möchte es verstehen, deshalb frag ich euch:

Vorarab: Ich wollte einen Münzgeldrechner schreiben (Quellcode ist unten), der einen Betrag, den man eingibt umwandelt in Münzgeld wechselt. Ziel dabei war es, so wenig wie möglich Münzen zu benutzen. Dies war die aufgabenstellung, nun kommt mein dazu passender code


Delphi-Quellcode:

procedure TForm1.edtEingabeChange(Sender: TObject);
var
  EingegebeneZahl: Currency;
  arGeld: array [0 .. 7] of Currency;
  i: Integer;
  zaehler: Integer;
begin
  // Array Füllen
  arGeld[0] := 2;
  arGeld[1] := 1;
  arGeld[2] := 0.50;
  arGeld[3] := 0.20;
  arGeld[4] := 0.10;
  arGeld[5] := 0.05;
  arGeld[6] := 0.02;
  arGeld[7] := 0.01;

  EingegebeneZahl := StrToFloat(edtEingabe.Text);
  mmoLog.Lines.Add(FloatToStr(EingegebeneZahl));

  for i := 0 to 7 do
  begin
    zaehler := 0;
    repeat
      if EingegebeneZahl < arGeld[i] then
      begin
        break;
      end;
      mmoLog.Lines.Add('Operation: '+FloatToStr(EingegebeneZahl)+' - '+FloatToStr(arGeld[i]));
      EingegebeneZahl := EingegebeneZahl - arGeld[i];
      mmoLog.Lines.Add(FloatToStr(EingegebeneZahl));

      Inc(zaehler);
    until arGeld[i] > EingegebeneZahl;
    if arGeld[i] = 2 then
      lbl2.Caption := IntToStr(zaehler);
    if arGeld[i] = 1 then
      lbl1.Caption := IntToStr(zaehler);
    if arGeld[i] = 0.50 then
      lbl050.Caption := IntToStr(zaehler);
    if arGeld[i] = 0.20 then
      lbl020.Caption := IntToStr(zaehler);
    if arGeld[i] = 0.10 then
      lbl010.Caption := IntToStr(zaehler);
    if arGeld[i] = 0.05 then
      lbl005.Caption := IntToStr(zaehler);
    if arGeld[i] = 0.02 then
      lbl002.Caption := IntToStr(zaehler);
    if arGeld[i] = 0.01 then
      lbl001.Caption := IntToStr(zaehler);
  end;
end;


Dieser Code funktioniert, soweit ohne fehler!!


Ändert man jedoch den Datentyp von currency in double, single o.ä...Funkitioniert das Programm nicht mehr richtig!! (Als kleine veranschaulichung habe ich ein memo eingebaut, welches die aktion mitschreibt, die gerade durchgeführt wird). Es wird nach der Dritten bzw. 4 Berechnung alles ungenau, und es wird nicht mehr weiter berechnet.




Ich will wissen warum?!! warum ändert sich der wert von alleine/ wird ungenau...


Ich hoffe ein paar von euch können sich einen Reim darauf machen



LG

Paddy_VII

p.s: es geht nicht darum, ob der Code nun effizient ist, oder nicht ?
"Irren ist menschlich, aber wenn man richtigen Mist bauen will, braucht man einen Computer."
Dan Rather
  Mit Zitat antworten Zitat
Benutzerbild von Union
Union

Registriert seit: 18. Mär 2004
Ort: Luxembourg
3.492 Beiträge
 
Delphi 7 Enterprise
 
#2

AW: !!Riesenprobelm mit Datentypen!!

  Alt 25. Feb 2015, 13:45
Das liegt an der internen Darstellung. Ein Wert 0.5 wird als Double evtl. als 0.5000000128973 gespeichert. Für diese Fälle arbeite mit CompareValue mit einem entsprechenden Delta.
Ibi fas ubi proxima merces
sudo /Developer/Library/uninstall-devtools --mode=all
  Mit Zitat antworten Zitat
Benutzerbild von PaddyVII
PaddyVII

Registriert seit: 20. Nov 2014
Ort: Pforzheim
75 Beiträge
 
Delphi XE6 Enterprise
 
#3

AW: !!Riesenprobelm mit Datentypen!!

  Alt 25. Feb 2015, 13:53
aber warum genau wird der wert ungenau?? wir haben ihn als double angegeben, klar aber dann müsste doch auch 0,5 0,5000000000000000000000000000 werden und nich irgendwelche wahllosen zahlen hintendranhackseln
"Irren ist menschlich, aber wenn man richtigen Mist bauen will, braucht man einen Computer."
Dan Rather
  Mit Zitat antworten Zitat
Daniel
(Co-Admin)

Registriert seit: 30. Mai 2002
Ort: Hamburg
13.920 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: !!Riesenprobelm mit Datentypen!!

  Alt 25. Feb 2015, 13:56
Das hängt damit zusammen, dass auch ein moderner Computer Fließkommazahlen nicht exakt darstellen kann.
Schau mal dort:
http://de.wikipedia.org/wiki/Gleitkommazahl
Daniel R. Wolf
mit Grüßen aus Hamburg
  Mit Zitat antworten Zitat
Benutzerbild von PaddyVII
PaddyVII

Registriert seit: 20. Nov 2014
Ort: Pforzheim
75 Beiträge
 
Delphi XE6 Enterprise
 
#5

AW: !!Riesenprobelm mit Datentypen!!

  Alt 25. Feb 2015, 13:59
aber dann bedeutet das doch, dass es mit Single double usw. völlig schwachsinnig wäre zu rechnen, weil sie ehh ungenau werden oder?
"Irren ist menschlich, aber wenn man richtigen Mist bauen will, braucht man einen Computer."
Dan Rather
  Mit Zitat antworten Zitat
Daniel
(Co-Admin)

Registriert seit: 30. Mai 2002
Ort: Hamburg
13.920 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: !!Riesenprobelm mit Datentypen!!

  Alt 25. Feb 2015, 14:03
Wie genau brauchst Du es denn?
Jeder Datentyp hat eine auf n Stellen garantierte Genauigkeit.
Dann muss man schauen, was man braucht und kann dann den entsprechenden Datentyp wählen.

"Single" ist für viele, viele Fälle absolut ausreichend.
Daniel R. Wolf
mit Grüßen aus Hamburg
  Mit Zitat antworten Zitat
Benutzerbild von PaddyVII
PaddyVII

Registriert seit: 20. Nov 2014
Ort: Pforzheim
75 Beiträge
 
Delphi XE6 Enterprise
 
#7

AW: !!Riesenprobelm mit Datentypen!!

  Alt 26. Feb 2015, 09:53
Das liegt an der internen Darstellung. Ein Wert 0.5 wird als Double evtl. als 0.5000000128973 gespeichert. Für diese Fälle arbeite mit CompareValue mit einem entsprechenden Delta.
Wie würde denn das programm mit compareValue aussehen??
"Irren ist menschlich, aber wenn man richtigen Mist bauen will, braucht man einen Computer."
Dan Rather
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.660 Beiträge
 
Delphi 12 Athens
 
#8

AW: Genauigkeit von Datentypen

  Alt 26. Feb 2015, 10:09
Zitat:
if arGeld[i] = 2 then
if SameValue(arGeld[i], 2, 0.005) then oder
if CompareValue(arGeld[i], 2, 0.005) = EqualsValue then
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
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.399 Beiträge
 
Delphi 12 Athens
 
#9

AW: Genauigkeit von Datentypen

  Alt 26. Feb 2015, 10:15
Und wenn man die 0.005 weg lässt, dann wird automatisch ein typspezifischer Wert genommen.

Delphi-Quellcode:
const
  FuzzFactor = 1000;
  ExtendedResolution = 1E-19 * FuzzFactor;
  DoubleResolution = 1E-15 * FuzzFactor;
  SingleResolution = 1E-7 * FuzzFactor;

function SameValue(const A, B: Extended; Epsilon: Extended): Boolean;
begin
  if Epsilon = 0 then
    Epsilon := Max(Min(Abs(A), Abs(B)) * ExtendedResolution, ExtendedResolution);
  ...
end;

function IsZero(const A: Extended; Epsilon: Extended): Boolean;
begin
  if Epsilon = 0 then
    Epsilon := ExtendedResolution;
  ...
end;
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
mm1256

Registriert seit: 10. Feb 2014
Ort: Wackersdorf, Bayern
642 Beiträge
 
Delphi 10.1 Berlin Professional
 
#10

AW: Genauigkeit von Datentypen

  Alt 26. Feb 2015, 11:04
Ob es Sinn macht, statt Double Currency zu verwenden muss wohl jeder für sich selber entscheiden. Es kommt auf den Einzelfall an. Wenn z.B. ein Preis aus Menge mit bis zu 3 Nachkommastellen, Rabatt mit zwei Nachkommastellen, oder sogenannten Multi's wie sie bei Datanorm verwendet werden mit 3 Nachkommastellen....usw. berechnet werden muss, dann muss man Double und Currency mischen. Das ist auch nicht der Hit und darum kann es eleganter sein, die Doubles entsprechend zu behandeln.

if SameValue(arGeld[i], 2, 0.005) then
... in eine kleine Funktion packen, wenn man Double's für Beträge verwenden möchte

Delphi-Quellcode:
function GleicherBetrag(D1, D2: double): boolean;
begin
  Result := SameValue(D1, D2, 0.011);
end;
Gruss Otto PS: Sorry wenn ich manchmal banale Fragen stelle. Ich bin Hobby-Programmierer und nicht zu faul die SuFu zu benutzen
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 21:06 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