AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi Rundungsproblem mit MSSQL
Thema durchsuchen
Ansicht
Themen-Optionen

Rundungsproblem mit MSSQL

Ein Thema von gmc616 · begonnen am 8. Apr 2021 · letzter Beitrag vom 8. Apr 2021
Antwort Antwort
gmc616

Registriert seit: 25. Jun 2004
Ort: Jena
627 Beiträge
 
Delphi 10.3 Rio
 
#1

Rundungsproblem mit MSSQL

  Alt 8. Apr 2021, 14:56
Datenbank: MSSQL • Version: 2017 • Zugriff über: ADO
Hallo Delphi-Gemeinde,

ich haben einen komischen Effekt mit dem MSSQL-2017 im Delphi Rio (Win32/VCL-Anwendung) (WIN-10).
Ich möchte aus einer Rechnung die Summe aller Netto-Beträge, multipliziert mit deren Steuersatz als Brutto-Betrag ermitteln.
Aber irgendwie bekomme ich komische, falsch gerundete Beträge zurück.

Hier ein SQL der das Problem verdeutlichen soll:
Code:
Select
      sum (l.[Preis]) as Netto_Org
,    round(sum ([Preis]),2) as Netto_Round
,    206.5 * 1.19 as Brutto_Korrekt
,    round(206.5 * 1.19,2) as Brutto_Korrekt_round
,    sum( l.[Preis] * ( (r.steuersatz +100) / 100)) as Brutto_Org
,    sum( round(l.[Preis],2) * ( (r.steuersatz +100) / 100)) as Brutto_1
,    round(sum( round(l.[Preis],2) * ( (r.steuersatz +100) / 100)),2) as Brutto_2
,    round( sum( l.[Preis] * ( (r.steuersatz +100) / 100)),2) as Brutto_3
,    round( sum( l.[Preis] * 1.19) ,2) as Brutto_4
,    sum( round( l.[Preis] * 1.19 ,2)) as Brutto_5
,    sum( round( l.[Preis],2) * 1.19 ) as Brutto_6

from RechnungListe l, Rechnung r
where ....
group by r.steuersatz;
also Ergebnis dieser Query bekomme ich:
Code:
Netto_Org  Netto_Round Brutto_Korrekt Brutto_Korrekt_round Brutto_Org Brutto_1    Brutto_2    Brutto_3    Brutto_4    Brutto_5    Brutto_6
----------- ----------- -------------- -------------------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
206,5       206,5       245,735        245,74               245,735     245,735     245,73      245,73      245,73      245,72      245,735
Alle Einzelpositionen (l.[Preis]) sind floats und mit 2 Nachkommastellen gespeichert.
Der Netto-Betrag dieser Rechnung ist tatsächlich 206.50 (€), der Steuersatz ist 19 (%).
Schaut man sich aber [Brutto_1], [Brutto_2] oder [Brutto_3] an, stimmen die Rundung nicht. [Brutto_4], [Brutto_5] und [Brutto_6] sind Versuche mögliche Fehler auszuschließen.

Und jetzt wird's richtig wild.
Fetsche ich den [Netto_Org]-Wert heraus (im Debugger = 206.5) und schreibe den Wert in eine extended-Variable, multipliziere mit 1.19 erhalte ich wieder 245.735
Runde ich anschließen die Variable mit RoundTo (Wert,-2) bekomme ich 245.73 heraus, statt 245.74.

Delphi-Quellcode:
var
  nPow, nValue : extended;
begin
  nPow := power(10,2);

// Test 1
  nValue := ADO.FieldByName('Netto_org').AsFloat; // 206.5 laut Debugger
  nValue := nValue * 1.19;
  nValue := RoundTo(nValue,-2);
// = 245.73 , falsch

// Test 2
  nValue := ADO.FieldByName('Netto_org').AsFloat; // 206.5 laut Debugger
  nValue := nValue * 1.19;
  nValue := nValue * nPow;
  nValue := nValue + 0.5;
  nValue := trunc(nValue); // <- hier passiert etwas komisches !! 24574 wird zu 24573 ???
  nValue := nValue/nPow;
// = 245.73 , falsch

// Test 3
  nValue := 206.5;
  nValue := nValue * 1.19;
  nValue := RoundTo(nValue,-2);
// = 245.74 , korrekt.

// Test 4
  nValue := ADO.FieldByName('Netto_round').AsFloat; // ebenfalls 206.5 laut Debugger
  nValue := nValue * 1.19;
  nValue := RoundTo(nValue,-2);
// = 245.74 , korrekt.
Irgendwie bekomme ich von der Datenbank nicht den korrekten Wert zurück, bzw. die Rundung im SQL-Server funktioniert nicht richtig.
Kann mir jemand erklären was hier schief läuft?

Danke.
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.874 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Rundungsproblem mit MSSQL

  Alt 8. Apr 2021, 14:58
Du summierst gerundete Werte, damit summierst Du auch die Rundungsdifferenzen
Markus Kinzler
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.222 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: Rundungsproblem mit MSSQL

  Alt 8. Apr 2021, 15:01
Für Geldbeträge empfiehlt sich der passend Datentyp Money (MS SQL Server) bzw. die Methoden AsCurreny wenn man in Delphi damit arbeitet.
das mit sollten die Rundungsprobleme die sich durch die Verwendung von Single/Extended-Datentypen ergeben erledigen.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
gmc616

Registriert seit: 25. Jun 2004
Ort: Jena
627 Beiträge
 
Delphi 10.3 Rio
 
#4

AW: Rundungsproblem mit MSSQL

  Alt 8. Apr 2021, 15:13
Wo summiere ich im Test-1 und Test-2 gerundete Werte?

Der Tipp mit AsCurreny funktioniert.
Hätte ich auch selbst drauf kommen können, das mal auszuprobieren. Manchmal ist man einfach festgefahren.

Aber wieso funktioniert das? Was ist der Unterschied zu AsFloat?

Auch Brutto_3-Betrag hätte doch einen korrekten Wert zurück liefern müssen. Aber das liegt wohl am Datentyp.

Geändert von gmc616 ( 8. Apr 2021 um 15:19 Uhr)
  Mit Zitat antworten Zitat
Andreas13

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

AW: Rundungsproblem mit MSSQL

  Alt 8. Apr 2021, 15:30
Hallo gmc616,
Du solltest anstelle von nPow := power(10,2); besserConst nPow = 100 schreiben, denn power(..) arbeitet mit Logarithmen, wodurch automatisch Rundungsfehler in den letzten Stellen entstehen.

Bis Du Dir sicher, daß der Wert von Netto_Org genau 206,5 ist? Ein winziger Rundungsfehler bei der internen binären Darstellung z.B. von 206,4999999999 würde schon dazu führen, daß korrekt auf 245,73 abgerundet wird. Kannst Du den aktuellen Wert Netto_Org auch 18 Stellen ausdrucken lassen? Im Debugger sieht man oft nur gerundete Werte.

Welchen Datentyp hat Netto_Org in Deiner Datenbank?

Gruß, Andreas
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
Andreas13

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

AW: Rundungsproblem mit MSSQL

  Alt 8. Apr 2021, 15:44
Der Datentyp Currency ist allerdings keine „Allzweckwaffe“, denn die seine festen 4 Nachkommastellen sind nur bei Addition und Subtraktion von Währungseinheiten (mit max. 4 Nachkommastellen!) exakt. Bei Multiplikation, Division und sonstigen transzendenten Operationen pflanzen sich die Rundungsfehler in hintere Nachkommastellen fort und das Problem bleibt bestehen.

Wenn Du nPow := power(10,2); anstellen einer Konstanten-Deklaration verwenden willst, dann solltest Du eine einfache Funktion Function IntegerPotenz(Basis, Potenz: Integer): Integer; schreiben, welche die Basis (hier: 10) n-mal (her: 2-mal) miteinander multipliziert. Dann bist Du flexibler.
Gruß, Andreas
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
Andreas13

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

AW: Rundungsproblem mit MSSQL

  Alt 8. Apr 2021, 15:53
Wenn Du nur die Integer-Potenzen von 10 benötigtst, könntest Du so vorgehen:
Delphi-Quellcode:
Function IntPower_of_10(n: Word): Extended;
// Integerpotenzen von 10
VAR
  i, Pow: Integer;
Begin
  Pow:= 1;

  For i:= 1 To n Do
  Begin
    Pow:= Pow*10;
  End;

  Result:= Pow;
End;{IntPower_of_10}
Gruß, Andreas
Grüße, Andreas
Wenn man seinem Nächsten einen steilen Berg hinaufhilft, kommt man selbst dem Gipfel näher. (John C. Cornelius)

Geändert von Andreas13 ( 8. Apr 2021 um 16:21 Uhr)
  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 19:51 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