AGB  ·  Datenschutz  ·  Impressum  







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

Nur x Nachkommastellen von Float

Ein Thema von anse · begonnen am 2. Okt 2023 · letzter Beitrag vom 10. Okt 2023
Antwort Antwort
Andreas13

Registriert seit: 14. Okt 2006
Ort: Nürnberg
731 Beiträge
 
Delphi XE5 Professional
 
#1

AW: Nur x Nachkommastellen von Float

  Alt 8. Okt 2023, 09:57
Hallo Michael,
so einfach läßt sich das Problem der Rundungsfehler leider nicht lösen. Eigentlich gibt es überhaupt keine Lösung dafür. Denn es wird nicht nur abgerundet, sondern auch mal aufgerundet. Und dann müßte Dein plusepsilon ein minusepsilon sein.

Sorry, Deine Lösung ist nicht „mathematisch“, sondern willkürlich an diese eine Aufgabe zugeschnitten.

Was einzig alleine hilft, sind mehr, vieeeeeel mehr Stellen, also nicht Double, sondern Extended, quad precision, oder oft nur Multi-Precisions-Arithmetik (MPA) mit hunderten ... tausenden Nachkommastellen, wobei das Ergebnis am Ende aller Berechnungen auf das Zielformat gerundet wird.

Über diese Problematik haben sich schon viele Forscher den Kopf zerbrochen und zahlreiche gute Artikel und Fachbücher publiziert, ohne ein Patentrezept verkünden zu können...
Grüße, Andreas
Wenn man seinem Nächsten einen steilen Berg hinaufhilft, kommt man selbst dem Gipfel näher. (John C. Cornelius)
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
778 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Nur x Nachkommastellen von Float

  Alt 8. Okt 2023, 13:35
Hallo Michael,
Denn es wird nicht nur abgerundet, sondern auch mal aufgerundet. Und dann müßte Dein plusepsilon ein minusepsilon sein
Es darf für positive Zahlen nie minusepsilon sein:
Wenn ein Dezimalbruch binär periodisch ist, dann wird das System beim Speichern von double wahrscheinlich entweder aufrunden, wenn das 53ste Bit=1 ist oder aber ab Bit 53 abschneiden (und damit abrunden). Das System speichert also entweder z1<z oder z2>z. Im Intervall ]z1,z2[ kann das Format nix speichern.
Es gibt also 2 Fälle.
1. Das System hat abgeschnitten oder abgerundet und speichert z1. Wir addieren Epsilon und landen bei z2>z und trunc() wird den erwarteten Wert ermitteln.
2. Das System hat aufgerundet und hat z2 gespeichert. Wir könnten also mit z2 weiterrechnen und trunc() wäre OK. z3:=plusepsilon(z2)=z2+Epsilon ist der nächstgrössere speicherbare Wert nach z2. Also z3>z2>z. Wenn die Stellengenauigkeit vom verwendeten Format gross genug ist für das gegebene Problem, dann fällt es nicht ins Gewicht, dass wir nicht mit z2 weiterrechnen. Wenn wir aber wie du schreibst abrunden würden, dann würden wir bei z1 := z2-Epsilon landen. Wir wissen aber z1<z und damit rechnen "wir" beim trunc() wieder falsch. Also keine gute Idee.
Michael Gasser

Geändert von Michael II ( 8. Okt 2023 um 15:53 Uhr)
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
778 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Nur x Nachkommastellen von Float

  Alt 8. Okt 2023, 14:09
.

Sorry, Deine Lösung ist nicht „mathematisch“, sondern willkürlich an diese eine Aufgabe zugeschnitten.

Was einzig alleine hilft, sind mehr, vieeeeeel mehr Stellen, also nicht Double, sondern Extended, quad precision, oder oft nur Multi-Precisions-Arithmetik (MPA) mit hunderten ... tausenden Nachkommastellen, wobei das Ergebnis am Ende aller Berechnungen auf das Zielformat gerundet wird.

Über diese Problematik haben sich schon viele Forscher den Kopf zerbrochen und zahlreiche gute Artikel und Fachbücher publiziert, ohne ein Patentrezept verkünden zu können...
Du schreibst, die Lösung sei auf das Problem zugeschnitten. Dafür gebe ich dir 100 Punkte . Eine Lösung sollte auf die gestellte Aufgabe zugeschnitten sein. Die vorher angegebenen Vorschläge lieferten zwischen 123.000000 und 123.999999 in mindestens 496 Fällen nicht das korrekte Resultat.

Mit Willkür hat das nix zu tun. Aber du hast Recht, das ist 1. Semster Informatik Stoff und hat mit Mathe nicht viel zu tun - eher mit Rechnen.

Du schreibst Extended[/URL"]extended wäre besser. Mehr Binärstellen nützen leider nicht viel:
Dezimalbrüche, welche binär periodisch sind können in einem binären Format (wie von single, double, extended verwendet) nie genau gespeichert werden. Mit extended erhöhst du lediglich die Stellengenauigkeit (extended: floor(log(2^63)/log(10) - generell log(2^n)/log(2) = n*log(2)/log(10) - d.h. pro weiteres Bit für den fraction Teil gewinnst du ungefähr 0.301 Stellen). Wenn du für das in #1 geschilderte Problem als Input Zahlen mit vielen Stellen erwartest, dann nimm extended. Für die trunc()erei wirst du bei solchen Datentypen um das Epsilon nicht herumkommen.

Es gibt sicher Leute, welche das Speichern und das Rechnen mit solchen Daten als "Forschung" bezeichnen. Mich wundert heute nix mehr
Michael Gasser

Geändert von Michael II ( 8. Okt 2023 um 15:55 Uhr)
  Mit Zitat antworten Zitat
mmw
(Gast)

n/a Beiträge
 
#4

AW: Nur x Nachkommastellen von Float

  Alt 8. Okt 2023, 20:14
Hallo,

als Korrektur zu #3, (mit DOUBLE gab's Probleme)

Delphi-Quellcode:
function GetDigits(const AValue: Extended; Digits: Integer): Integer;

var
    value:Extended;
    value1:Real;

begin
   value:=frac(AValue)*intpower(10,digits);
   value1:=value;
   Result := trunc(value1);
end;

Gruß
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
778 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Nur x Nachkommastellen von Float

  Alt 8. Okt 2023, 22:33
Hallo,

als Korrektur zu #3, (mit DOUBLE gab's Probleme)

Delphi-Quellcode:
function GetDigits(const AValue: Extended; Digits: Integer): Integer;

var
    value:Extended;
    value1:Real;

begin
   value:=frac(AValue)*intpower(10,digits);
   value1:=value;
   Result := trunc(value1);
end;

Gruß
Hoi mmw,

das Problem bleibt. Wenn ein Dezimalbruch eine unendlich binäre Darstellung hat (also binär irgend ein periodischer Bruch ist), dann kannst du den dezimalen Wert binär mit den Formaten single, double, extended nicht genau abspeichern. Das System kann nur die nächstkleinere oder nächstgrössere (durch das Format (extended) vorgegebene) mögliche Zahl abspeichern. (siehe weiter oben)
In deinem Fall treten zum Beispiel zwischen 99.000001 und 99.999999 natürlich wiederum die "gleichen" 496 Probleme auf. U.a. wird für GetDigitsNeu( 99.101000, 3 ).ToString) 100 ausgegeben.
Dies geschieht auch, wenn du die von dir vorgeschlagene Konversion nach real (als double implementiert) weglässt und mit extended rechnest. Extended erlaubt dir lediglich eine grössere Stellengenauigkeit als double.
Michael Gasser

Geändert von Michael II ( 9. Okt 2023 um 19:49 Uhr)
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
778 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Nur x Nachkommastellen von Float

  Alt 10. Okt 2023, 17:49
Für extended kannst du das Epsilon so addieren:

Delphi-Quellcode:
function plusepsilone(e : extended):extended;
var h : System.TExtended80Rec absolute e;
begin
   h.Frac := h.Frac+1;
   Result := e;
end;
(Hinweis: Prüft nicht, ob h.frac maximal = 1111.....111 ist.)
Michael Gasser
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.874 Beiträge
 
Delphi 12 Athens
 
#7

AW: Nur x Nachkommastellen von Float

  Alt 10. Okt 2023, 18:00
Das geht dann aber auch etwas schlanker:
Delphi-Quellcode:
uses
  System.Sysutils;

...

function plusepsilone(const e : extended):extended;
begin
   Result := e;
   Result.Frac := Result.Frac+1;
end;
Könnte man auch noch als inline deklarieren.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  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 11:58 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