Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Rundung bei Verwendung von DisplayFormat (https://www.delphipraxis.net/186102-rundung-bei-verwendung-von-displayformat.html)

Ralf Kaiser 3. Aug 2015 15:15

Rundung bei Verwendung von DisplayFormat
 
Halli Hallo,

Wir lassen verschiedene Werte die aus einer Datenbank gelesen werden in einem Report anzeigen. Diese Werte sollen mit 2 Nachkommastellen angezeigt werden. Das ist über "DisplayFormat" festgelegt.

Wir habe nun das Problem, dass diese Anzeige scheinbar nicht korrekt arbeitet. Um das zu prüfen habe ich die Daten im Report durch eine einzelne Reportvariable ersetzt der ich einen festen Wert zugewiesen habe: z.B. 0.375000000000.

Dieser Testwert wird mit dem zweistelligen DisplayFormat als "0,37" angezeigt. Meiner Meinung nach müsste dies aber "0,38" sein, oder liege ich da falsch?

Was noch dazu kommt: Auf einem System das zum Test benutzt wird ist ein Windows 2003 Server installiert und dort wird "0,38" als Ergebnis erzeugt. Auf anderen Systemen (Win7, Win2008 Server) ist der angezeigte Wert immer "0,37"

Ich habe den gesamten Code kontrolliert ob da irgendwo an den FPU-Einstellungen etwas geändert wird (SetRoundMode oder Set8087CW usw.), was aber nicht der Fall ist.

Kann jemand erklären, warum die Anzeige mit "DisplayFormat" nicht korrekt ist und warum sie sich von System zu System unterscheiden kann?

Danke schon mal für Tipps oder Hinweise,
Ralf

Union 3. Aug 2015 16:00

AW: Rundung bei Verwendung von DisplayFormat
 
Verschiedene Werte... darf ich raten, ftFloat? Schreib am Besten eine eigene Rundung im GetText. Du wurdest ge-ieeet ;)

Ralf Kaiser 3. Aug 2015 16:22

AW: Rundung bei Verwendung von DisplayFormat
 
Zitat:

Zitat von Union (Beitrag 1310809)
Verschiedene Werte... darf ich raten, ftFloat? Schreib am Besten eine eigene Rundung im GetText. Du wurdest ge-ieeet ;)

Ich hatte als Test den Wert 0.375000000000 benutzt. Durch die zusätzlichen Nullen die den Wert genauer definieren sollten eigentlich diese Effekte keine Rolle mehr spielen (wie ich schrieb kommt der Wert für den Test nicht mehr aus der Datenbank sondern wird als Konstante fest zugewiesen).

Was mich irritiert ist der Umstand, dass sich die slebe Software auf 2 verschiedenen Systemen unterschiedlich verhält. Kann denn eine andere (fremde) Software die gleichzeitig läuft da einen Einfluss ausüben?

Dejan Vu 3. Aug 2015 16:32

AW: Rundung bei Verwendung von DisplayFormat
 
Das Problem ist, das 0.375 nicht exakt darstellbar ist. Mich wundert es zwar, das dies auf unterschiedlichen Systemen unterschiedlich gerundet (bzw. intern dargestellt) wird, aber ich habe Ähnliches vor Jahren erlebt.
(Ziemlich amateurhafte) Abhilfe:
Delphi-Quellcode:
Function RoundToDecimal (aValue, aGranularity : Double);
begin
  result := (0.500000000001 + Trunc(aValue/aGranularity))*aGranularity;
end;
Getippt und nicht getestet.

Bei mir ging es um Cent-Beträge und da hatte mir das gereicht. Aufruf für 2 Nachkommastellen übrigens mit 'RoundToDecimal(value,0.01)'.

Ralf Kaiser 3. Aug 2015 16:41

AW: Rundung bei Verwendung von DisplayFormat
 
Zitat:

Zitat von Dejan Vu (Beitrag 1310812)
Das Problem ist, das 0.375 nicht exakt darstellbar ist.

Das sollte aber doch bei dem angegebenen Literal "0.375000000000" nicht der Fall sein. Das ist auf 12 Stellen genau angegeben und zeigt trotzdem den Effekt (oder ignoriert Delphi die zusätzlichen Nullen und nimmt an ich hätte "0,375" angegeben (mit der daruas resultierenden Ungenauigkeit)?

Uwe Raabe 3. Aug 2015 16:57

AW: Rundung bei Verwendung von DisplayFormat
 
Zitat:

Zitat von Ralf Kaiser (Beitrag 1310800)
einen festen Wert zugewiesen habe: z.B. 0.375000000000.

Dieser Testwert wird mit dem zweistelligen DisplayFormat als "0,73" angezeigt. Meiner Meinung nach müsste dies aber "0,74" sein, oder liege ich da falsch?

Ziemlich falsch! Da müsste eher sowas wie 0,37 oder 0,38 rauskommen.

Uwe Raabe 3. Aug 2015 17:08

AW: Rundung bei Verwendung von DisplayFormat
 
Zitat:

Zitat von Dejan Vu (Beitrag 1310812)
Das Problem ist, das 0.375 nicht exakt darstellbar ist.

Doch, eigentlich schon:

Single (Hex): 3EC00000
Double (Hex): 3FD8000000000000

0.375 lässt sich auch als 1.5 / 4 schreiben, was zu einem Exponenten von -2 oder normiert 125 bzw. 1021 führt. Die 1 vor dem Komma wird implizit angenommen und die 0.5 lässt sich als Mantisse binär exakt mit einer 1 und vielen Nullen darstellen.

Ralf Kaiser 3. Aug 2015 17:08

AW: Rundung bei Verwendung von DisplayFormat
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1310815)
Zitat:

Zitat von Ralf Kaiser (Beitrag 1310800)
einen festen Wert zugewiesen habe: z.B. 0.375000000000.

Dieser Testwert wird mit dem zweistelligen DisplayFormat als "0,73" angezeigt. Meiner Meinung nach müsste dies aber "0,74" sein, oder liege ich da falsch?

Ziemlich falsch! Da müsste eher sowas wie 0,37 oder 0,38 rauskommen.

Ooops. Sorry. Das war ein Vertipper. Ich habe es im Originalpost korrigiert. :oops:

Uwe Raabe 3. Aug 2015 17:09

AW: Rundung bei Verwendung von DisplayFormat
 
Zitat:

Zitat von Ralf Kaiser (Beitrag 1310817)
Ich habe es im Originalpost korrigiert. :oops:

Mach nochmal...

Ralf Kaiser 3. Aug 2015 17:18

AW: Rundung bei Verwendung von DisplayFormat
 
Das muss die Hitze sein :oops::oops::oops:

Neumann 3. Aug 2015 18:15

AW: Rundung bei Verwendung von DisplayFormat
 
Ich vermute mal, dass es sich um Fastreport handelt. Dessen Variablen sind zunächst erst mal vom Typ Variant und werden intern dann - wenn eine Zahl erkannt oder erwartet wird in den Typ Double umgewandelt.

Vielleicht ist da das Problem. Abhilfe ist, dem Report immer schon vorher gerundete Werte zu übergeben. Es gibt doch die Funktion Roundto die das macht, damit habe ich keine Probleme in der Hinsicht.

Ralf Kaiser 3. Aug 2015 18:23

AW: Rundung bei Verwendung von DisplayFormat
 
Nein. Es handelt sich um ReportBuilder.

Aber ich werde morgen mal recherchieren ob die intern so ähnlich arbeiten.

Dejan Vu 3. Aug 2015 20:32

AW: Rundung bei Verwendung von DisplayFormat
 
Zitat:

Zitat von Ralf Kaiser (Beitrag 1310814)
Zitat:

Zitat von Dejan Vu (Beitrag 1310812)
Das Problem ist, das 0.375 nicht exakt darstellbar ist.

Das sollte aber doch bei dem angegebenen Literal "0.375000000000" nicht der Fall sein.

Das stimmt zufällig, da hast Du Recht. Übrigens auch ohne die '000000'.

Ich war zu sehr auf 0.735 getrimmt.... Wenn das wirklich bei 0.375 so ist, dann ist das wirklich merkwürdig.

Das Einzige, was ich mir vorstellen kann, sind unterschiedliche Rundungsverfahren (Bankers Rounding vs. 'Normal'). Aber das hast Du ja schon gecheckt... Mystisch.

Medium 3. Aug 2015 22:03

AW: Rundung bei Verwendung von DisplayFormat
 
Nur noch mal um das klar zu stellen, auch wenn es hier glatt darstellbar ist: Es ist völlig egal wie viele Nullen du deinem Literal anhängst. Wenn ein Wert nicht perfekt in einem IEEE Float abgebildet werden kann, kann er es einfach nicht. Egal welche esoterischen Literale einem da noch so einfallen. Geht. Nicht.

(Da der konkrete Wert hier aber exakt darstellbar wäre, muss irgendwo auf dem Weg vom Programm auf den Report-Canvas etwas seltsames passieren.)


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:46 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