Autor Beitrag
buSC
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 39



BeitragVerfasst: Di 22.12.09 12:12 
hallo liebe forumer

ich habe in einer stelle in meinem delphi code die Ueberraschung, dass 0.3-0.3=5.5e-17 gehabt wobei je 0.3 inhalt eines double-variables ist.

warum habe ich kein null bekommen ??!!!


im Voraus Danke fuer eure Antwort

Moderiert von user profile iconGausi: Topic aus Algorithmen, Optimierung und Assembler verschoben am Di 22.12.2009 um 11:16
Moderiert von user profile iconNarses: Überflüssige Zeilenumbrüche/Leerzeilen entfernt.
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8554
Erhaltene Danke: 481

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Di 22.12.09 12:16 
Das sind die üblichen Ungenauigkeiten bei der Darstellung von Float-Werten. Sämtliche dieser Typen sollten nie mit "=" überprüft werden, sondern mit den passenden Funktionen wie IsEqual. Da wird dann Gleichheit bis auf eine gewisse Genauigkeit überprüft.

Zur Ausgabe sollte man passend runden.

_________________
We are, we were and will not be.
buSC Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 39



BeitragVerfasst: Di 22.12.09 13:05 
danke fuer die schnelle Antwort

aber mein Problem ging es nicht um Gleichheit sodern um deise subtraktion 0.3-3.0 die null ergeben musste aber gibt 5.5e-17 zueruck.

wobei je 0.3 in einem double variable im laufe des Programms entstanden ist.

aber ich will null(0) als ergebnis.


danke Im voraus fuer die Antwort

Moderiert von user profile iconNarses: Überflüssige Zeilenumbrüche/Leerzeilen entfernt.
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8554
Erhaltene Danke: 481

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Di 22.12.09 13:27 
Und genau das geht halt nicht. Man bekommt bei solchen Rechnungen nicht das exakte Ergebnis. Das liegt daran, dass einige Werte, die im Zehnersystem "schön" aussehen, im Dualsystem eben mehr (oder viel mehr) Stellen brauchen. Und dabei kommt es dann zu Rundungsartefakten.

0.3 - 0.3 ist dann nicht gleich 0, sondern nur ungefähr gleich 0. ;-)

Dir bleibt da nur, die Ausgabe auf eine kleinere Genauigkeit zu beschränken (FloatToStrF), oder besondere Ergebnisse nachzuarbeiten.

_________________
We are, we were and will not be.
Gammatester
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 328
Erhaltene Danke: 101



BeitragVerfasst: Di 22.12.09 13:35 
Ohne Deine genaue Vorgehensweise kann man nur raten. Wenn d1 und d2 double-Variablen sind, so gilt immer d1 - d1 = 0 und d2 - d2 = 0. Interessant ist z.B.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
d1 := 0.3;
d2 := 0.1;
d2 := 3*d1;
writeln(d2-d1);

Das Ergebnis ist 5.55111512312578E-0017. Die Erklärung ist folgende: 0.1=1/10 und 0.3=3/10 sind nicht exakt im Binärsystem darstellbar, so wie 1/3 nicht exakt als endliche Dezimalzahl darstellbar ist. Die internen Darstellungen sind
ausblenden Quelltext
1:
2:
3:
  0.1 = 3FB999999999999A
  0.3 = 3FD3333333333333
3*0.1 = 3FD3333333333334

0.3 und 3*0.1 unterscheiden sich im letzen Bit ungefähr so wie sich 2*(1/3) = 0.6666666666 sich von 2/3 = 0.6666666667 im Dezimalsystem mit 10 Nachkommastellen unterscheiden. Das letzte Bit ergibt die 5.55E-17.

Gruß Gammatester
F34r0fTh3D4rk
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Di 22.12.09 22:32 
Ich habs jetzt nicht getestet, aber ich bin mir ziemlich sicher, dass 0.3 und 0.3 ohne die Anwendung arithmetischer Operationen die selbe interne Repräsentation haben :mrgreen:.

Beispiel (wie gesagt, ungetestet):
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
var
  a, b, c: double;
begin
  a := 0.3
  b := 0.3
  c := a-b; // = 0.0
end;

Intern würde 0.3 afaik durch 0 01111101 00110011001100110011010(IEE 754) o.Ä. repräsentiert werden (statt double habe ich hier einfach mal float genommen).
Bei der Subtraktion müsste also trotz alledem 0.0 herauskommen.

Ich gehe einfach mal davon aus, dass es so ist, dass in deinen beiden double-Variablen nicht wirklich 0.3 drinsteht und daher das von user profile iconGammatester beschriebene Problem auftritt.