AGB  ·  Datenschutz  ·  Impressum  







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

Plötzlich auftretenes Rundungsproblem

Ein Thema von Sourcemaker · begonnen am 15. Dez 2004 · letzter Beitrag vom 16. Dez 2004
Antwort Antwort
Seite 2 von 2     12   
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#11

Re: Plötzlich auftretenes Rundungsproblem

  Alt 15. Dez 2004, 13:49
Zitat von Sourcemaker:
ich bin gestern von einem Kunden über eine Rundungsproblematik hingewiesen worden.
Das Problem tritt bei den Funktionen FormatFloat und Str auf. Eine Berechnung die im
vorliegenden Fall 9,32 EUR ergeben müsste 3,45*3/0,9=9,315 wird durch die o.g. Funktionen
als 9,31 EUR ausgegeben.
Es gibt da zwei verschiedene Rundungsverfahren:
* Kaufmänisches Runden: bei x.5 wird immer aufgerundet
* "Banker's rounding": bei x.5 wird abwechselnd auf- und abgerundet

Delphi verwendet "Banker's rounding". Die Auf- und Abrundungen sollen sich in der Masse gegenseitig aufheben.
Kaufmännisches Runden geht so:
Delphi-Quellcode:
function CommercialRound(const X: Extended): Int64;
begin
  Result := Trunc(X);
  if Frac(Abs(X)) >= 0.5 then
    Result := Result + Sgn(X);
end;
Die Art & Weise, mit der die Funktion Round() arbeitet, hängt übrigens von der aktuellen
Einstellung des FPU Flags-Registers ab.
(Wahrscheinlich die Ursache für unterschiedlichem Verhalten von Round auf versch. Rechnern)
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von Jelly
Jelly

Registriert seit: 11. Apr 2003
Ort: Moestroff (Luxemburg)
3.741 Beiträge
 
Delphi 2007 Professional
 
#12

Re: Plötzlich auftretenes Rundungsproblem

  Alt 15. Dez 2004, 13:50
Zitat von Luckie:
Wie runden denn "Bänker"?
Immer zu Ihren Gunsten


Das ganze Problem hängt wohl mit der Floatarithmetik zusammen. In was für einen Datentyp wird denn 3,45*3/0,9 gespeichert... Probier doch mal double oder extended, und kuck was dann bei raus kommt.
  Mit Zitat antworten Zitat
Benutzerbild von ibp
ibp

Registriert seit: 31. Mär 2004
Ort: Frankfurt am Main
1.511 Beiträge
 
Delphi 7 Architect
 
#13

Re: Plötzlich auftretenes Rundungsproblem

  Alt 15. Dez 2004, 13:56
Die Funktionsweise von RoundTo kann mit der Prozedur Set8087CW oder der Funktion SetRoundMode gesteuert werden
  Mit Zitat antworten Zitat
Benutzerbild von dizzy
dizzy

Registriert seit: 26. Nov 2003
Ort: Lünen
1.932 Beiträge
 
Delphi 7 Enterprise
 
#14

Re: Plötzlich auftretenes Rundungsproblem

  Alt 15. Dez 2004, 15:43
Zitat von Jelly:
Das ganze Problem hängt wohl mit der Floatarithmetik zusammen. In was für einen Datentyp wird denn 3,45*3/0,9 gespeichert... Probier doch mal double oder extended, und kuck was dann bei raus kommt.
Genau dort würde ich den "Fehler" (es ist eigentlich nur eine Ungenauigkeit) vermuten. Ich hatte hier mal was zur Speicherung von Fließkommazahlen geschrieben - das erklärt evtl. das Verhalten.

Es kann nämlich durchaus sein, dass du 9.315 hinschreibst, aber gerechnet wird (aus technischen Gründen) u.U. mit soetwas wie 9.314999999956. Dann stimmte das Abrunden wieder.

Der Typ "Currency" könnte imho hilfreich bei der Problemlösung sein.

Gruss,
Fabian
Fabian K.
INSERT INTO HandVonFreundin SELECT * FROM Himmel
  Mit Zitat antworten Zitat
Benutzerbild von Sourcemaker
Sourcemaker

Registriert seit: 3. Sep 2003
Ort: Westoverledingen
264 Beiträge
 
Delphi 11 Alexandria
 
#15

Re: Plötzlich auftretenes Rundungsproblem

  Alt 16. Dez 2004, 12:40
Tut mit leid das ich mich erst jetzt wieder einschalte war total im Stress.

Dir Rechnung sollte lauten 3,45*3*0,9=9,315 anstatt 3,45*3/0,9=9,315. Sorry.

Ich konnte mittlerweile die Sache aufklären:
Ich rufe an bestimmten Programmpunkten eine externe DLL auf die in CaVo (Visual Object)
geschrieben ist und ich rufe nicht FormatFloat direkt auf sondern eine Funktion:

Delphi-Quellcode:
function FormStr(const v: Variant; nLen: integer; nDec: integer = 0): string;
var
   cFormat : string;
procedure MakeFormat;
begin
   if nLen > 3 then
      cFormat := '#,'+cFormat;
end;
begin
   if nDec = 0 then
   begin
      cFormat := '##0';
      MakeFormat;
   end
   else
   begin
      cFormat := '##0.'+Replicate('0',nDec);
      nLen := nLen-nDec-1;
      MakeFormat;
   end;
   Result := FormatFloat(cFormat,v);
end;
Diese Funktion bekommt den Zahlenwert als Variant übertragen und funktioniert solange ich nicht
die besagte DLL aufgerufen habe. Ich habe noch eine weitere ähnliche Funktion die mit Str arbeitet
wo es zum gleichen Problem kommt.
Die Lösung liegt zum einen in der Verwendung von Currency-Variablen (wo es möglich ist) zum anderen auf die angesprochenen Funktionen bezogen auf zusätzliche Rundungsfunktionen.
Delphi-Quellcode:
function FormStr(v: Variant; nLen: integer; nDec: integer = 0): string;
var
   cFormat : string;
procedure MakeFormat;
begin
   if nLen > 3 then
      cFormat := '#,'+cFormat;
end;
begin
   if nDec = 0 then
   begin
      cFormat := '##0';
      MakeFormat;
   end
   else
   begin
      cFormat := '##0.'+Replicate('0',nDec);
      nLen := nLen-nDec-1;
      MakeFormat;
   end;
   case VarType(v) of
   varCurrency : v := MyRoundC(v,nDec);
   varInteger : ;
   else v := MyRound(v,nDec);
   end;
   Result := FormatFloat(cFormat,v);
end;

function MyRoundC(nZahl:Currency;nDec:integer):Currency;
var
  i: integer;
begin
  for i := 1 to nDec do nZahl := nZahl * 10;
  nZahl := Int(nZahl + iif(nZahl > 0, 0.5, -0.5));
  for i := 1 to nDec do nZahl := nZahl / 10;
  Result := nZahl;
end;
Wie gesagt damit löse ich die Probleme aber interessieren würde es mich doch was die ext. DLL
mit den Variants anstellt. Falls also jemand eine Idee hat ...
Ist die Round-Funktion Ok oder gibt es bessere Lösungen ?

Grüße

Frank
Frank
  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 00: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