AGB  ·  Datenschutz  ·  Impressum  







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

Extended rundet bei Addition automatisch

Ein Thema von Delphi-Narr · begonnen am 24. Mär 2012 · letzter Beitrag vom 25. Mär 2012
Antwort Antwort
Benutzerbild von Delphi-Narr
Delphi-Narr

Registriert seit: 29. Aug 2009
Ort: Duisburg
437 Beiträge
 
Delphi 2007 Professional
 
#1

Extended rundet bei Addition automatisch

  Alt 24. Mär 2012, 21:29
Hallo,

ich habe ein eigentlich recht banales Problem: Ich möchte zu einer Variable des Typs Extended einen weiteren Extended-Wert hinzuaddieren.

Der zu addierende Wert ist mit 2,5E-18 sehr klein, ist aber entscheidend.

Ist der Ursprungswert meiner Variable X = 0, so ist das Ergebnis korrekt. 0+2,5E-18 ergibt 2,5E-18.
Möchte ich jedoch zum Wert X = 1 den Wert addieren, erhalte ich immer noch 1...

Wie kann ich dieses Problem beheben?

Viele Grüße!
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

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

AW: Extended rundet bei Addition automatisch

  Alt 24. Mär 2012, 21:32
Garnicht?
Die signifikanten Stellen, also die Auflösung reicht nicht unbedingt aus.

Du brauchst einen anderen Typen, welcher eine höhere Genauigkeit besitzt,
oder du mußt deinen Wert auf mehrere Variablen aufteilen. (was quasi auf's Selbe rauskommt)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (24. Mär 2012 um 21:34 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.356 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Extended rundet bei Addition automatisch

  Alt 24. Mär 2012, 21:35
Indem du selbst rechnest, ohne Extended als Typ. Der hat eine zu geringe Genauigkeit. Intern funktioniert die Fließkommadarstellung wie der Name schon sagt, indem das Komma fließt. Die Genauigkeit ist aber begrenzt und ist bei Extended glaube ich 14 Stellen oder so. Solange du nun nur einen Wert 18 Stellen nach dem Komma hast, ist das ok. Das ist eben dieser Wert 18 Stellen nach dem Komma.

Wenn du nun aber einen Wert vor dem Komma hast und der mit den Nachkommastellen addiert wird, ist die Differenz zu groß als dass das in der Genauigkeit darstellbar wäre.

Bei solchen hochpräzisen Berechnungen bleibt daher nur diese entweder nach Möglichkeit so zu optimieren, dass sich das Problem nicht stellt oder eine präzisere Berechnung selbst zu implementieren.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

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

AW: Extended rundet bei Addition automatisch

  Alt 24. Mär 2012, 21:52
Extended hat maximal 18-19 signifikante Dezimalstellen. (ungefähr 18,1845... Dezimalstellen)
Die Berechnung liegt also knapp an der Grenze.

Es gibt aber einen Unterschied.
Der Debugger, FloatToStr usw. runden aber oftmals schon auf 15-16 Stellen, für die Anzeige. (Double)

Somit könnte die Berechnung grade noch so stimmen.
Code:
                   12
0,0000000000000000025

1
1,0

also
1 234567890123456789 = Dezimalstellen
1,000000000000000003 = Ergebnis
Für die Anzeige könnte aber die 0,00..03 weggerundet werden .... es werden 0,0 angezeigt, aber es sind 1,000000000000000003 vorhanden, was sich prüfen läßt, indem man 18 explizit mit Dezimalstellen anzeigen läßt.

Nja, mit 1,... sind es etwa 19 signifikante Dezimalstellen, wärend 4,... nur 18 Dezimalstellen ergibt.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (24. Mär 2012 um 22:02 Uhr)
  Mit Zitat antworten Zitat
Panthrax

Registriert seit: 18. Feb 2005
286 Beiträge
 
Delphi 2010 Enterprise
 
#5

AW: Extended rundet bei Addition automatisch

  Alt 25. Mär 2012, 01:07
Dieser Effekt wird auch Absobtion genannt; die größere Zahl absorbiert die kleinere Zahl. Wegen der begrenzten Genauigkeit von Gleikommazahlen, ist dies das beabsichtigte und "natürliche" Verhalten.

http://de.wikipedia.org/wiki/Gleitko..._absorption.29

Die Möglichkeiten, das zu verhindern sind begrenzt und am Ende steht die Implementierung eines eigenen Typs, der die Genauigkeitsforderungen erfüllt. Vielleicht gibt es aber auch eine andere Lösung, weil "man weiß, was man tut": Ich wollte einmal Zahlenreihen summieren, regelmäßig bestehend aus Zahlen, die nicht alle gleichzeitig in den Genauigkeitsbereich passten. Nachdem eine erste große Zahl vorkam oder die Summe zu groß wurde, wurden alle nachfolgenden, kleinen absorbiert. Aufgrund der Vielzahl der Zahlen war der Fehler für nachfolgende Berechnungen einfach zu groß. Meine Lösung war, erst die Zahlenreihen zu sortieren und dann bei der kleinsten beginnend zu summieren. So haben die kleinen Zahlen ihr Gewicht in der Gesamtberechnung nicht verloren, und der Fehler konnte angemessen reduziert werden.
"Es gibt keine schlimmere Lüge als die Wahrheit, die von denen, die sie hören, missverstanden wird."
  Mit Zitat antworten Zitat
Benutzerbild von Delphi-Narr
Delphi-Narr

Registriert seit: 29. Aug 2009
Ort: Duisburg
437 Beiträge
 
Delphi 2007 Professional
 
#6

AW: Extended rundet bei Addition automatisch

  Alt 25. Mär 2012, 10:47
Also einen komplett neuen Typ zu implementieren geht mir für meine Zwecke zu weit...
Ich habe quasi eine Schleife, in der zum Ursprungswert X immer eine kleine Zahl hinzuaddiert wird. Dafür ist das letzte Ergebnis für mich von Bedeutung. Jedes Zwischenergebnis soll auch ausgegeben werden können. Dann muss ich wohl leider die Anzahl der Zwischenergebnisse reduziere, sodass der zu addierende Wert größer wird. Ist für die Genauigkeit zwar nicht so gut, aber immer noch besser als gar keine Veränderung.

Danke für die Hilfe!
  Mit Zitat antworten Zitat
Panthrax

Registriert seit: 18. Feb 2005
286 Beiträge
 
Delphi 2010 Enterprise
 
#7

AW: Extended rundet bei Addition automatisch

  Alt 25. Mär 2012, 11:17
Das klingt doch gut!

Delphi-Quellcode:
var
  Summe, KleineSumme, KleinerWert: Extended;
    // KleinerWert hier nur als Platzhalter

{ ... }

Summe := 1;
KleineSumme := 0;

for I := 0 to N - 1 do
begin
  KleineSumme := KleineSumme + KleinerWert;
    // erst die kleinen Werte summieren

  WriteLn(Summe + KleineSumme);
    // für die Ausgabe summieren;
    // irgendwann ist KleineSumme groß genug
    // und wird nicht mehr absorbiert
end;

Summe := Summe + KleineSumme;
  // dann die großen und kleinen Werte summieren.
"Es gibt keine schlimmere Lüge als die Wahrheit, die von denen, die sie hören, missverstanden wird."
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

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

AW: Extended rundet bei Addition automatisch

  Alt 25. Mär 2012, 12:44
Du könntest sogar noch mehr Ungenauigkeiten rausrechnen.
Delphi-Quellcode:
KleineSumme := 0;
for I := 0 to N - 1 do
begin
  KleineSumme := KleinerWert * I;
    // erst die kleinen Werte summieren

  WriteLn(Summe + KleineSumme);
    // für die Ausgabe summieren;
    // irgendwann ist KleineSumme groß genug
    // und wird nicht mehr absorbiert
end;

Summe := Summe + KleineSumme;
Delphi-Quellcode:
for I := 0 to N - 1 do
begin
  WriteLn(Summe + (KleinerWert * I));

end;

Summe := Summe + (KleinerWert * N);
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#9

AW: Extended rundet bei Addition automatisch

  Alt 25. Mär 2012, 15:36
Wenn du nur + und - verwendest, kannst du auch einfach in ein besser aufgelöstes Intervall skalieren, und bei der Ausgabe Exponentialdarstellung nehmen, oder im String ein paar Nullen zwischenpappen. (Dann natürlich am besten um 10er Potenzen skalieren )
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
gammatester

Registriert seit: 6. Dez 2005
999 Beiträge
 
#10

AW: Extended rundet bei Addition automatisch

  Alt 25. Mär 2012, 17:09
Wenn es nur um Summation geht, kannst Du meine aus meiner AMath-Unit die Funktionen
Delphi-Quellcode:
function sum2x(const a: array of extended; n: integer): extended;
  {-Compute accurate sum(a[i], i=0..n-1) of extended vector}
function sum2x(const a: array of extended; n: integer): extended;
  {-Compute accurate sum(a[i], i=0..n-1) of extended vector}
benutzen, die Genaugkeit wird dadurch ca verdoppelt. Intern verwenden sie den Algorithmus von "T. Ogita, S.M. Rump, and S. Oishi, Accurate sum and dot product".
  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 22:37 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