![]() |
AW: MwSt. wird falsch berechnet. (Einige nutzen eine falsche Formel!)
um zu verstehen, was firebird da macht, führ mal zB in ibexpert so was aus
insert into x select 150000000.000 * 19.000 / 119.000 as A, 19.000 * 150000000.000 / 119.000 as B from RDB$DATABASE; auf basis von deinem select und den resultierenden Datentypen wird die tabelle von ibexpert dynamisch erstellt um 3 zahlen miteinander zu multiplizieren/dividiren, die jeweils 3 Nachkommastellen haben und so wie im sql geschrieben wurde, werden zB als numeric(18,3) von firebird interpretiert. Das resultierende Datenfeld wird also als numeric(18,9) erzeugt. Gedankenexperiment: wenn man nun ein mal 0.001*0.001*0.001 miteinander verlustfrei multiplizieren will, dann musst du im result ein numeric(18,9) ermöglichen, sonst hast du ungeplant schon rundungsfehler. Das vermeidet Firebird durch die gewählten Datentypen. in der Tabelle x die da oben erstellt wird, sind die ergebnisfelder auch genau dieser Datentyp, das wilde zwischendurch mal casten und rounden macht das Ergebnis nicht besser, sondern führt ebenen ein, an denen die Abweichungen entstehen, die hier bemängelt werden. Und nun mal als Hinweis wo das Problem ist (bei dir an der Tastatur) multipliziere folgende Zahlen select 10000000000.00001*0.00001*0.00001 from RDB$DATABASE; diese Rechnung erfordert damit nix weggerundet wird 15 nachkommastellen, ein insert into wie oben würde dafür einen numeric(18,15) erzeugen, blöderweise sind dafür dann aber von den 18 Stellen nur noch 3 vor dem Komma möglich, d.h. den Wert 1000 wirst du darin schon nicht mehr speichern können. hier ein Beispiel bei dem es knallt: select 999900000.00111*0.11111*0.0111 from RDB$DATABASE; Unsuccessful execution caused by system error that does not preclude successful execution of subsequent statements. Integer overflow. The result of an integer operation caused the most significant bit of the result to carry. ------------------------------------------------------------------------------------------------------------------- SQLCODE: -901 SQLSTATE: 22003 GDSCODE: 335544779 da ist keine zahl dabei, die die üblichen datentypen sprengt, aber das zwischenergebnis kann nicht mit relevanter genauigkeit erstellt werden. Und vom dialekt 1 und dessen gruseligkeiten reden wir da gar nicht erst, alle beispiele oben basieren auf dialekt 3. Das Problem entsteht durch durch mehrfachoperation pro Zeile Welche workarounds gibt es: -Wenn das wirklich ein Problem ist, das du lösen musst, dann steig um auf fb>=4 dort gibt es numeric bis 34 statt 18, damit kommen aber nicht alle client libs und komponenten klar -wenn in deinem Zahlenraum >=zweistellige millionenbeträge gebraucht werden, sind für Währungen meistens 2 Nachkommastellen ausreichend, also numeric(18,2). was dann für Steuersätze erforderlich ist, ergibt sich durch das umfeld. Umrechnungsfaktoren können aber auch noch ganz andere Ebenen sein, alte säcke wissen noch was mit der Zahl 1,95583 verbunden war. -kombiniere im sql die werte immer mit nur einem operator oder nutze ab fb3 eigene stored functions für eine sauberere berechnung, der du die werte übergibst und die dann diese zeilenweise selber über geeignete Variablen mit ausreichender Genauigkeit das ergebnis korrekt berechnet. SQL selber kann zwar auch direkt im Befehl für Rechenoperationen benutzt werden, hat aber wie oben geschildert Grenzen, die du berücksichtigen musst. -Alternativ steht dir auch double precision in firebird als Datentyp zur verfügung, der resultiert aber kaufmännisch betracht in anderen problemen. Eine torte für 10 € gesamtpreis aufgeteilt in 3 stück zu je 10€/3 preislich festgelegt zeigt dann aufgrund der Endlichkeit auf dem Preisschild 3,33€ als Stückpreis an, wenn jemand dann davon aber 3 stück kauft, könnte es den Kunden wundern, warum deine Kasse 10€ auswirft und nicht wie im Kopf ausgrechnet 9,99€.Technisch kann nämlich im Double 3 1/3 stehen, auch wenn das im Front end nicht komplett dargestellt wird, sind da auch unsichtbare teile in den Nachkommastellen relevant). -alternativ kannst du auch alle zahlen die währungsbeträge darstellen, zB dann als int128 darstellen und damit zb jeden Betrag in ct verwalten, auch da sollte wenig verloren gehen, ein 128 bit integer hat ausreichend stellen (für seriennummern aller Atome in einem menschlichen Körper würde in etwa ein int78 ausreichen, da ist also luft nach oben selbst für so eine wenig hilfreiche seriennummernerfassung, soll aber nur ein vorstellung geben, über welche datentypen man da redet). numeric >=10 <=18 wird intern von fb dialekt 3 immer als int64 benutzt numeric >=5 <=9 wird intern von fb dialekt 3 immer als int32 benutzt numeric <=4 wird intern von fb dialekt 3 immer als int16 benutzt das war auch schon in fb2.x so Zusammenfassung: Firebird rechnet nichts falsch, sondern das was man dort als SQL und basisdatentyp bzw Werte vorgibt. Und Ja, auch die reihenfolge ist wichtig, weil auch firebird mit den verfügbaren Datentypen intern klar kommen muss, insbesondere wenn selber noch zwischendurch castings und rundungen gemacht werden. Wenn die Ergebnisse nicht das sind was du erwartest, musst du den Weg zum Ergebnis anpassen. Ob dann execute block die werte mit passenden Variablen sauber zusammenstellt oder sp oder trigger zwischenwerte ermitteln ist relativ egal, wild verschaltelte sum/cast/round etc. sind dann aber selten eine gute strategie. Eigene Funktionen als Stored functions bieten einen sehr zuverlässigen weg. Für fast alle normalen Zahlenwerte ist die sql multiplikation aber einwandfrei implementiert. Der Titel von dem Thread ist aus meiner sicht irreführend |
AW: MwSt. wird falsch berechnet. (Einige nutzen eine falsche Formel!)
Zitat:
MwSt = Brutto - (Brutto / 1,19) Das erste Brutto in die Klammer ziehen: MwSt = (Brutto * 1,19 - Brutto) / 1,19 1,19 in zwei Summanden auflösen: MwSt = (Brutto * (1 + 0,19) - Brutto) / 1,19 Binomische Formel: MwSt = (Brutto * 1 + Brutto * 0,19 - Brutto) / 1,19 0 entfernen: MwSt = Brutto * 0,19 / 1,19 Mit 100 erweitern (komplett sinnfrei): MwSt = Brutto * 19 / 119 Klammer setzen (komplett sinnfrei): MwSt = Brutto * (19 / 119) |
AW: MwSt. wird falsch berechnet. (Einige nutzen eine falsche Formel!)
Nicht vorsagen :)
Aber warum so umständlich? Brutto - Brutto/1,19 // ausklammern = Brutto * (1 - 1/1,19) // Brüche erweitern = Brutto * (119/119-100/119) // Brüche subtrahieren = Brutto * 19/119 |
AW: MwSt. wird falsch berechnet. (Einige nutzen eine falsche Formel!)
Zitat:
|
AW: MwSt. wird falsch berechnet. (Einige nutzen eine falsche Formel!)
Zitat:
Das Runden ist entscheidend, schaue, das deine Datentypen nicht „Von alleine“ anfangen zu runden! Der Datentype currency ist nicht dafür geeignet. Der ist max. für Endsummen der richtige Datentype! |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:17 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