AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Ceil Floor Log10 - Rundungsfehler, Überlauf o.ä. (?)
Thema durchsuchen
Ansicht
Themen-Optionen

Ceil Floor Log10 - Rundungsfehler, Überlauf o.ä. (?)

Ein Thema von hansmaad · begonnen am 18. Mai 2011 · letzter Beitrag vom 19. Mai 2011
Antwort Antwort
Seite 2 von 2     12   
idefix2

Registriert seit: 17. Mär 2010
Ort: Wien
1.027 Beiträge
 
RAD-Studio 2009 Pro
 
#11

AW: Ceil Floor Log10 - Rundungsfehler, Überlauf o.ä. (?)

  Alt 18. Mai 2011, 22:56
Zitat:
Deine Idee ist zwar ein Disaster-Konzept, weil Differenzen von zwei Sprungfunktionen geradezu danach schreien, solche Effekte hervorzurufen
Das ist der springende Punkt: Gleitkommaarithmetik kann von der Systematik her keine ganz exakten Werte liefern, und schon gar nicht, wenn wie hier eine transzendentale Funktion wie der Dezimallogarithmus aufgerufen wird. MINIMALE Abweichungen vom mathematisch exakten Ergebnis sind da nicht überraschend, sonden völlig normal und zu erwarten. Diese Abweichungen sind in einer Grössenordnung, die normalerweise keine Rolle spielt.

Wenn Du jetzt aber als Ergebnis einer solchen Funktion eine ganze Zahl erwartest, und es kommt etwas heraus, das im Rahmen der erlaubten Abweichung kleiner ist als die erwartete Zahl, dann wirkt sich die danach angewendete Funktion Floor natürlich katastrophal aus, weil der Dezimalteil, in dem Fall vielleicht 0.99999999999999999999999999, abgeschnitten wird. Daß das aber kein Fehler von Delphi, sondern ein Fehler im Programmierkonzept ist, muss jedem klar sein, der sich auch nur im Entfertnesten mit numerischer Mathematik und der Rundungsproblematik beschäftigt hat.

Zitat:
Siehe da: Dort kommt das richtige Ergebnis raus.
Ob das Ergebnis der log10 Funktion 7.000000000000000001 oder 7.000000000000000000 oder 6.999999999999999999999 liefert, ist ein reines Lotteriespiel - in den beiden ersten Fällen liefert floor(log10(x)) dann die erwartete 7, im anderen Fall eben 6. Das Ergebnis ist deshalb nicht in einem Fall richtig und im anderen Fall falsch (in Hinblick auf die Umsetzung durch den Compiler), sondern in allen Fällen im Rahmen der von einer Gleitkommaarithmetik erwartbaren Genauigkeit.

Das Problem wirst Du auch nicht los, indem Du die Rechengenauigkeit erhöhst, weil, egal auf wieviele Stellen Du rechnest, in der allerletzten Binärstelle eine Abweichung sein wird, und ganz egal wie klein die Abweichung ist, wenn sie zufällig nach unten geht, schneidet floor den Dezimalteil weg.

Geändert von idefix2 (18. Mai 2011 um 23:22 Uhr)
  Mit Zitat antworten Zitat
hansmaad

Registriert seit: 25. Feb 2010
52 Beiträge
 
Delphi 2010 Professional
 
#12

AW: Ceil Floor Log10 - Rundungsfehler, Überlauf o.ä. (?)

  Alt 19. Mai 2011, 07:23
Also erstmal Danke für die hilfreichen Hinweise.
Vielleicht können wir dann ja noch klären, was die richtige Implementierung für das Problem ist. Gesucht ist eine Funktion, die die nächst niedrige und eine Funktion, die die nächst höhere Zehnerpotenz zu einer Gleitkommazahl zurückgibt. Und zwar als Ganzzahl, die den Exponenten angibt.
  Mit Zitat antworten Zitat
Jens01

Registriert seit: 14. Apr 2009
670 Beiträge
 
#13

AW: Ceil Floor Log10 - Rundungsfehler, Überlauf o.ä. (?)

  Alt 19. Mai 2011, 09:57
Floor(Round(Log10(min)))

Geändert von Jens01 (19. Mai 2011 um 10:01 Uhr)
  Mit Zitat antworten Zitat
idefix2

Registriert seit: 17. Mär 2010
Ort: Wien
1.027 Beiträge
 
RAD-Studio 2009 Pro
 
#14

AW: Ceil Floor Log10 - Rundungsfehler, Überlauf o.ä. (?)

  Alt 19. Mai 2011, 10:14
Es gibt zu Deiner Frage zwei Probleme, die man berücksichtigen muss:
Das erste hast Du im Ursprungsposting angesprochen, nämlich die Genauigkeit der Funktion selbst. Die Funktion ist nichtlinear, sie hat bei jeder Zehnerpotenz eine Sprungstelle. Nachdem auch Gleitkommaarithmetik exakt rechnet, solange nur ganze Zahlen und die Grundrechenarten involviert sind, kannst Du in einer Schleife abfragen, ob Dein x grösser als 1,10,100 etc. ist, eine einfache Multiplikation einer ganzen Realzahl mit 10 wird sicher keine Rundungsfehler produzieren. Bei den Dezimalzahlen 0.1, 0.01 ist die Angabe des Sprungpunkts aber nicht exakt möglich, weil diese Zahlen in Binärdarstellung eine periodische Mantisse haben.

Damit hast Du aber das zweite Problem noch nicht gelöst, nämlich die Genauigkeit des Funktionsparameters x selbst: Wo kommt der her? Wenn der das Ergebnis einer Geitkommaberechnung ist, dann kann sich auch dort der kleinste Rundungsfeher dahingehend auswirken, dass bei einer Zahl, die z.B. ganz knapp kleiner als 100 sein sollte, etwas herauskommt, was ganz knapp grösser als 100 ist und deshalb das Ergebnis der Gesamtberechnung einen unerwarteten Wert liefert. Oder anders herum, der Parameter, den Du übergibst, hätte genau 10 sein sollen, ist aber als Ergebnis einer Gleitkommarechnung 9.999999999999999999999999999999994, und das Ergebnis Deiner Funktion stimmt deshalb nicht mit dem, was Du erwartest, überein, obwohl die Funktion selbst ganz genau und ohne Rundungsfehler rechnet.

Zitat:
Floor(Round(Log10(min)))
Das wird ganz falsche Ergebnisse bringen, floor(round(0.7))=1 statt der erwarteten 0. Floor auf einen gerundeten Wert anzuwenden ist übrigens sinnlos, weils der gerundete Wert ja schon eine ganze Zahl ist und der nachfolgende floor-Aufruf nichts mehr verändert.

Geändert von idefix2 (19. Mai 2011 um 10:46 Uhr)
  Mit Zitat antworten Zitat
gammatester

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

AW: Ceil Floor Log10 - Rundungsfehler, Überlauf o.ä. (?)

  Alt 19. Mai 2011, 10:47
Hier ein Vorschlag, der mit einer Toleranz für den log10 arbeitet. Die Funktionen schauen nach, ob x nahe bei einer Zehnerpotenz liegt. Wenn nein, werden die nächst niedrigeren bzw. höheren Potenzen genommen. Die Nähe-Toleranz tol sollte sinnvollerweise nicht kleiner als ca 1e-15 gewählt werden.
Delphi-Quellcode:
{---------------------------------------------------------------------------}
function minpower10(x: extended): integer;
  {-Berechnet für x>0 den maximalen Integerwert mit 10^result <= x}
const
  tol = 1e-9;
var
  lx: extended;
  li: integer;
begin
  lx := log10(x);
  li := round(lx);
  if abs(li - lx) > tol then li := floor(lx);
  minpower10 := li;
end;


{---------------------------------------------------------------------------}
function maxpower10(x: extended): integer;
  {-Berechnet für x>0 den minimalen Integerwert mit 10^result >= x}
const
  tol = 1e-9;
var
  lx: extended;
  li: integer;
begin
  lx := log10(x);
  li := round(lx);
  if abs(li - lx) > tol then li := ceil(lx);
  maxpower10 := li;
end;

Geändert von gammatester (19. Mai 2011 um 10:50 Uhr)
  Mit Zitat antworten Zitat
idefix2

Registriert seit: 17. Mär 2010
Ort: Wien
1.027 Beiträge
 
RAD-Studio 2009 Pro
 
#16

AW: Ceil Floor Log10 - Rundungsfehler, Überlauf o.ä. (?)

  Alt 19. Mai 2011, 10:55
Das geht einfacher, indem Du für die Funktion floor einfach 1E-9 zum Parameter addierest und für die Funktion Ceil einfach 1E-9 vom Parameter abziehst.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


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 14:44 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