Afrondings puzzelvraag

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • JDVB
  • Registratie: September 2003
  • Laatst online: 20-05 10:38

JDVB

✅ ⟵ vinkje

Topicstarter
Hoi,

Ik probeer een oud boekhoudprogramma te begrijpen, dan wel specifiek hoe een factuurtotaal berekend wordt om zodoende zelf vanuit de database ervan een kopie factuur te kunnen genereren (i.p.v. door oude dozen heen te moeten graven).
Dit programma berekend de BTW naar mijn idee een beetje vreemd:
afronden(afronden(aantal * verkoopprijs / (1+BTW%) * BTW%) * (1 - korting%))

Tot zover kom ik, echter rest mij 1 probleem, wanneer het BTW bedrag eindigt op halve centen rond het systeem dit de ene keer naar boven af, de andere keer naar beneden.
Waar kan dat aan liggen, of zie ik iets wat wel logisch is over het hoofd hoe de BTW bepaald wordt?


Een aantal voorbeelden:
AantalprijskortingBTWBTW berekendBTW uit systeem
14,5030%6%0,1750,18
112,9530%21%1,5751,58
115,9525%6%0,6750,67
42,0030%6%0,3150,31
129,9525%6%1,2751,28


Wanneer ik slechts 1 keer afrond dan kom ik nog veel minder dichtbij de door het systeem berekende BTW bedragen. Wanneer ik de betreffende artikelen over alle facturen vergelijk dan zijn de bedragen per artikel consequent.
Ik dacht eerst dat dit wellicht te maken had met de wijze waarop bedragen in het systeem opgeslagen worden (exponent van het een of ander, om zo in 4 bytes een groter getal te kunnen stoppen), echter zou dat vervolgens ook zijn impact moeten hebben op de exclusief en inclusief prijzen, echter heb ik daarbij nog geen afwijkingen gevonden (alle afrondingen van halve centen lijken omhoog te gaan zoals mij normaal lijkt).

Iemand enig idee hoe ik (met deze gegevens) alsnog sluitende facturen kan reproduceren vanuit artikelregels?

Ik ben geen recruiter ofzo, maar wel op zoek naar een collega devver. Typescript/Node/Angular/etc en liefst op HBO niveau. We zitten op een prachtige locatie tussen bos en heide op de Utrechtse heuvelrug. Mijn PM box staat open!


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
JDVB schreef op maandag 08 oktober 2012 @ 16:32:
Tot zover kom ik, echter rest mij 1 probleem, wanneer het BTW bedrag eindigt op halve centen rond het systeem dit de ene keer naar boven af, de andere keer naar beneden.
Waar kan dat aan liggen, of zie ik iets wat wel logisch is over het hoofd hoe de BTW bepaald wordt?
Banker's rounding.

[edit1]
Oh, wacht, je tabel suggereert iets anders :P

[edit2]
afronden(afronden(...)). Dan vermoed ik toch Banker's rounding maar dan zou ik 't even moeten narekenen :P

[ Voor 20% gewijzigd door RobIII op 08-10-2012 16:41 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • JDVB
  • Registratie: September 2003
  • Laatst online: 20-05 10:38

JDVB

✅ ⟵ vinkje

Topicstarter
Bij inkomende facturen wordt de BTW overigens wel weer anders berekend dan bij uitgaande.
Heel vreemd om 1 artikel voor dezelfde prijs in een verkoop en inkoop order te stoppen en vervolgens dan toch 1 of 2 cent verschil te kunnen hebben.
Maar de berekening is consequent per artikel/aantal/prijs combinatie ofwel naar boven ofwel naar beneden afgerond. Dus reproduceren zou dan toch ook moeten kunnen, ik vraag me alleen af via welke kronkel.

Hoe reproduceer ik dit vervolgens om dezelfde afronding te kunnen benutten? (liefst binnen PHP)

[ Voor 14% gewijzigd door JDVB op 08-10-2012 16:50 ]

Ik ben geen recruiter ofzo, maar wel op zoek naar een collega devver. Typescript/Node/Angular/etc en liefst op HBO niveau. We zitten op een prachtige locatie tussen bos en heide op de Utrechtse heuvelrug. Mijn PM box staat open!


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Het zou handig zijn, als extra informatie, als je zou vermelden wélk boekhoudsysteemen, eventueel (mocht je 't weten), in welke taal dit geschreven is. Er zijn -tig manieren van afronden (en niet elke is even "goed" voor bepaalde doeleinden).

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • Serpie
  • Registratie: Maart 2005
  • Laatst online: 01-07-2023
Bij sommige systemen worden alle verschillen tussen afronding en orginele berekening opgeslagen om op een volgende correctie dat mee te nemen.

Dan kun je binnen 1 factuur zelfs verschillen krijgen!

code:
1
2
3
            prijs        korting       bedrag
Artikel A  24,90         35%           16,19
Artikel B  24,90         35%           16,18


De prijs na korting is 16,185. Op de eerste regel wordt deze naar boven afgerond. Het verschil van afronding wordt in de tweede regel weer meegenomen, wat dus resulteert in 16,18 (=16,185 - 0,005).

Acties:
  • 0 Henk 'm!

  • JDVB
  • Registratie: September 2003
  • Laatst online: 20-05 10:38

JDVB

✅ ⟵ vinkje

Topicstarter
't gaat om een oud dos systeem dat samenwerkt met een pervasive database.

En bedragen zijn consequent afgerond per artikel. Dus elke keer als artikel 1 op 0,5 cent eindigt dan gaat deze altijd dezelfde kant op in de afronding. Oplopende verschillen had ik al uitgesloten door dit bij een aantal facturen uit te proberen.

Zelfs oplopende verschillen gescheiden geprobeerd voor zowel btw hoog als laag afzonderlijk (zou ook niet weten waarom je dat zou willen maar toch).

[ Voor 73% gewijzigd door JDVB op 08-10-2012 17:02 ]

Ik ben geen recruiter ofzo, maar wel op zoek naar een collega devver. Typescript/Node/Angular/etc en liefst op HBO niveau. We zitten op een prachtige locatie tussen bos en heide op de Utrechtse heuvelrug. Mijn PM box staat open!


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
JDVB schreef op maandag 08 oktober 2012 @ 16:43:
Hoe reproduceer ik dit vervolgens om dezelfde afronding te kunnen benutten? (liefst binnen PHP)
Dit benutten is illegaal ivm Uitvoeringsbesluit omzetbelasting art 5a...
http://wetten.overheid.nl...ldigheidsdatum_08-10-2012

Overigens snap ik niet hoe jij de BTW berekend. Bij 6% BTW, 25% korting en originele prijs incl. btw van 15.95 kom ik op 0,677=>0,68E BTW. ;)

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • JDVB
  • Registratie: September 2003
  • Laatst online: 20-05 10:38

JDVB

✅ ⟵ vinkje

Topicstarter
pedorus schreef op maandag 08 oktober 2012 @ 20:08:
Dit benutten is illegaal ivm Uitvoeringsbesluit omzetbelasting art 5a...
http://wetten.overheid.nl...ldigheidsdatum_08-10-2012

Overigens snap ik niet hoe jij de BTW berekend. Bij 6% BTW, 25% korting en originele prijs incl. btw van 15.95 kom ik op 0,677=>0,68E BTW. ;)
Lijkt mij ook logisch, zou ik verwacht hebben, is echter niet wat het boekhoudprogramma doet. Dit is dus ook niet mijn berekening, wel mijn poging die te reproduceren.
Wellicht niet optimaal, als iemand een meer passende manier ziet hoe ik zodanig kan afronden dat ik altijd op de gegeven BTW bedragen uitkom dan ben ik blij.

Daarnaast vraag ik me even af of de link die jij aandraagt van toepassing is op afzonderlijke orderregels waarvan de BTW niet afzonderlijk vermeld wordt, al is dat niet relevant omdat ik de betreffende software zelf niet kan of wil aanpassen. Ik wil enkel de rekenwijze kunnen reproduceren om zodoende vanuit de database oude (kopie) facturen op te kunnen vragen.

Daarbij moeten kopie facturen overeen komen met de originelen, lijkt me niet dat die zelfs maar 1 cent van elkaar mogen verschillen. Maar om het factuurtotaal goed te kunnen krijgen moet de som der delen overeen komen met de originele berekening. Die lijkt dus niet op factuurtotaal af te ronden maar per order regel twee maal.

Daarbij lijkt de afronding los te staan van de factuur omdat per bedrag consequent de zelfde kant op afgerond wordt. Op alle facturen hetzelfde regelbedrag de zelfde kant op afgerond dus, ongeacht regelnummer en wat er voor of na op de factuur komt.

Ik zou 's nachts een job kunnen laten lopen om alle afrondingen op te zoeken die op deze manier op halve centen eindigen, om vervolgens te groeperen op bedrag en vervolgens dit in een aparte afrondings tabel op kunnen slaan, echter wanneer er dan een nieuw bedrag dat op halve centen eindigt wordt verzonnen loopt het alsnog mis.

Daarbij lijkt me dat vervolgens nog redelijk wat handwerk om alle afrondingen handmatig op te moeten zoeken in het boekhoudprogramma om vervolgens te kunnen zien of er naar boven of naar beneden afgerond wordt.

Ik ben geen recruiter ofzo, maar wel op zoek naar een collega devver. Typescript/Node/Angular/etc en liefst op HBO niveau. We zitten op een prachtige locatie tussen bos en heide op de Utrechtse heuvelrug. Mijn PM box staat open!


Acties:
  • 0 Henk 'm!

  • P.O. Box
  • Registratie: Augustus 2005
  • Niet online
JDVB schreef op maandag 08 oktober 2012 @ 16:59:
't gaat om een oud dos systeem dat samenwerkt met een pervasive database.

En bedragen zijn consequent afgerond per artikel. Dus elke keer als artikel 1 op 0,5 cent eindigt dan gaat deze altijd dezelfde kant op in de afronding. Oplopende verschillen had ik al uitgesloten door dit bij een aantal facturen uit te proberen.

Zelfs oplopende verschillen gescheiden geprobeerd voor zowel btw hoog als laag afzonderlijk (zou ook niet weten waarom je dat zou willen maar toch).
zou het niet een floating point probleem kunnen zijn dat in "nieuwere programmeertalen" beter is afgevangen?
dus dat 1,185 bij het oude dosprogramma in het geheugen van de PC opgeslagen wordt als 1,1849999999, terwijl PHP hier iets beter mee kan omgaan?
Floating point numbers have limited precision. Although it depends on the system, PHP typically uses the IEEE 754 double precision format, which will give a maximum relative error due to rounding in the order of 1.11e-16. Non elementary arithmetic operations may give larger errors, and, of course, error propagation must be considered when several operations are compounded.
misschien gebruik het oude dossysteem geen IEEE 754, maar een voorloper daarvan?

[ Voor 23% gewijzigd door P.O. Box op 09-10-2012 11:09 ]


Acties:
  • 0 Henk 'm!

  • ZaPPZion
  • Registratie: Februari 2009
  • Laatst online: 03-06 11:43
Ja inderdaad, mijn eerste idee zou ook zijn dat het een floating point afronding betreft, dat dus de .5 niet .5 is maar .499999 of .500001

Acties:
  • 0 Henk 'm!

  • JDVB
  • Registratie: September 2003
  • Laatst online: 20-05 10:38

JDVB

✅ ⟵ vinkje

Topicstarter
P.O. Box schreef op dinsdag 09 oktober 2012 @ 11:03:
misschien gebruik het oude dossysteem geen IEEE 754, maar een voorloper daarvan?
Zoals: IEEE 854-1987?
Maar dan nog is de vraag hoe ik dat gedrag reproduceer.

Ik ben geen recruiter ofzo, maar wel op zoek naar een collega devver. Typescript/Node/Angular/etc en liefst op HBO niveau. We zitten op een prachtige locatie tussen bos en heide op de Utrechtse heuvelrug. Mijn PM box staat open!


Acties:
  • 0 Henk 'm!

  • Megamind
  • Registratie: Augustus 2002
  • Laatst online: 28-02 01:01
Waarschijnlijk kan dat niet meer in je nieuwe systeem omdat deze dus een ander soort afronding gebruikt, je zou het wel kunnen nabootsen op de originele computer.

Aangezien de bedragen al in de DB staan opgeslagen lijkt het nog fout te gaan bij de oude facturen.

Acties:
  • 0 Henk 'm!

  • JDVB
  • Registratie: September 2003
  • Laatst online: 20-05 10:38

JDVB

✅ ⟵ vinkje

Topicstarter
Ik zit zelf even aan twee varianten te denken:
  • ik kijk of ik binnen een functie, van het getal een float kan maken met voldoende lage precisie om betrouwbaar de afronding na te kunnen bootsen.
  • ik sla het getal in een nieuw tabel veld op als type float en lees deze vervolgens uit om deze daarna af te ronden.
Wellicht is optie 2 de gemakkelijkste, al schrijf ik liever niets weg in die database waardoor optie 1 toch mijn voorkeur zal hebben.

Ik ben geen recruiter ofzo, maar wel op zoek naar een collega devver. Typescript/Node/Angular/etc en liefst op HBO niveau. We zitten op een prachtige locatie tussen bos en heide op de Utrechtse heuvelrug. Mijn PM box staat open!


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Dit verhaal doet me denken aan http://thedailywtf.com/Articles/Immutable-Invoices.aspx :p
In ieder geval mag je voor nieuwe gevallen natuurlijk de BTW niet zo gaan afronden (de tussentijdse afronding is illegaal; wel kan dacht ik of per product worden afgerond, of per factuur).

Het valt me trouwens op dat gevonden afronding gelijk is aan die met 32-bit IEEE-754 floats. Voer de 32-bit hex waarde maar eens herin op http://babbage.cs.qc.edu/IEEE-754/

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • JDVB
  • Registratie: September 2003
  • Laatst online: 20-05 10:38

JDVB

✅ ⟵ vinkje

Topicstarter
Hmm, toch niet, wanneer ik 0,175 invul rond zou dat volgens die methode op 0,17 afgerond moeten worden.
Dus dat is hem helaas ook niet.

[ Voor 71% gewijzigd door JDVB op 11-10-2012 10:33 ]

Ik ben geen recruiter ofzo, maar wel op zoek naar een collega devver. Typescript/Node/Angular/etc en liefst op HBO niveau. We zitten op een prachtige locatie tussen bos en heide op de Utrechtse heuvelrug. Mijn PM box staat open!


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Zelfs niet iedere 0,175 zal steeds dezelfde kant op afgerond te worden natuurlijk. Die 0,175 is ontstaan uit een berekening met het kortingspercentage, wat verschillen in de latere (onzichtbare) cijfers achter de komma kan opleveren, wat voor een ander afrondresultaat kan zorgen. Je moet dus de gehele berekening overdoen met een taal die 32-bit floats ondersteund (java, c/c++, enz.) om er achter te komen of het hetzelfde is. :p

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • P.O. Box
  • Registratie: Augustus 2005
  • Niet online
misschien heb je hier wat aan: Wikipedia: Single-precision floating-point format

en dan specifiek onder het kopje : Converting from decimal representation to binary32 format
Conversion of the fractional part:

consider 0.375, the fractional part of 12.375. To convert it into a binary fraction, multiply the fraction by 2, take the integer part and re-multiply new fraction by 2 until a fraction of zero is found or until the precision limit is reached which is 23 fraction digits for IEEE 754 binary32 format.
0.375 x 2 = 0.750 = 0 + 0.750 => b−1 = 0, the integer part represents the binary fraction digit. Re-multiply 0.750 by 2 to proceed

0.750 x 2 = 1.500 = 1 + 0.500 => b−2 = 1

0.500 x 2 = 1.000 = 1 + 0.000 => b−3 = 1, fraction = 0.000, terminate
(het volgende is niet goed uitgedacht, maar even een eerste ingeving): als je bovenstaande doet en daarna weer terug-converteert, dan weet je of je op 0,49999 of 0,50001 bent uitgekomen, en weet je dus hoe het oude boekhoudprogramma heeft afgerond...

leuke uitdaging :D

[ Voor 12% gewijzigd door P.O. Box op 11-10-2012 11:29 ]


Acties:
  • 0 Henk 'm!

  • Big Womly
  • Registratie: Oktober 2007
  • Laatst online: 18-06-2024

Big Womly

Live forever, or die trying

afronden(afronden(aantal * verkoopprijs / (1+BTW%) * BTW%) * (1 - korting%))

In verkoopprijs zit blijkbaar al de BTW bijgerekend
verkoopprijs_excl * (1+BTW%) = verkoopprijs_incl
=> verkoopprijs_incl / (1+BTW%) = verkoopprijs_excl
verkoopprijs_excl * BTW% = BTW_bedrag

In het eerste deel van die berekening
afronden(aantal * verkoopprijs / (1+BTW%) * BTW%)
wordt berekend hoeveel BTW er nu eigenlijk betaald wordt. Dit wordt alvast afgerond omdat je nooit < € 0,01 betaald.

Vervolgens wordt de korting berekend op dat BTW bedrag
afronden(BTW_bedrag * (1 - korting%))
wat weer wordt afgerond omdat je nooit < € 0,01 betaald

[ Voor 12% gewijzigd door Big Womly op 11-10-2012 12:19 ]

When you talk to God it's called prayer, but when God talks to you it's called schizophrenia


Acties:
  • 0 Henk 'm!

  • JDVB
  • Registratie: September 2003
  • Laatst online: 20-05 10:38

JDVB

✅ ⟵ vinkje

Topicstarter
P.O. Box schreef op donderdag 11 oktober 2012 @ 11:26:
misschien heb je hier wat aan: [URL="http://en.wikipedia.org/wiki/Single-precision_floating-point_format"](het volgende is niet goed uitgedacht, maar even een eerste ingeving): als je bovenstaande doet en daarna weer terug-converteert, dan weet je of je op 0,49999 of 0,50001 bent uitgekomen, en weet je dus hoe het oude boekhoudprogramma heeft afgerond...

leuke uitdaging :D
Helaas gaat ook dit feestje niet op.
0,005 wordt afgerond naar 0, terwijl 1,005 wordt afgerond naar 1,01.
Anders zou ik simpel een tabelletje kunnen vullen met de 100 bedragen die van toepassing zijn, helaas is dat niet van toepassing. De afronding is dus afhankelijk van het gehele bedrag.
Zoals ik het vanuit de binaire data vertaald had, werd het bedrag in centen opgeslagen, dus zonder komma.
Ik kan me dus zo voorstellen dat het programma in het geheel niet achter de komma kijkt.
Overigens kan ik het gedrag ook niet reproduceren via bijvoorbeeld deze handige tool.

Een getal tijdelijk in een tabel weg schrijven werkt helaas ook niet, als ik deze uitlees krijg ik exact hetzelfde terug als ik erin stop.

Ik vermoed dat dit wel de goede richting is om op te zoeken, echter dat het geen IEEE 754 float is, maar wat anders.
Een functie waarmee ik vanuit de binaire data cijfers kan uitrekenen om te achterhalen wat het dan wel is:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
    function figure ($g1, $g2, $g3, $g4) {
//  echo $g1.' - '.$g2.' - '.$g3.' - '.$g4;
if($g1 < 0) {
    $g1 = 256 + $g1;
}
if ($g2 < 0) {
    $g2 = 256 + $g2;
}
if ($g3 < 0) {
    $g3 = 256 + $g3;
}
    $get = $g1 + $g2*256 + $g3*256*256;
// vergroting bepalen
// stap 1 de macht
    if($g3 > 128) {
    $addnum = 1;
    } else {
    $addnum = 0;
    }
    $macht = (2 * (abs($g4) - 63)) + $addnum;
// 1 cent stap bepalen
    $cent = 167772 / pow(2, $macht);
// aantal centen zonder uitzondering
    $euro = $get/$cent;
    
// correctie
if ($g3<129) {
    $correctie = 100*(0.5 * pow(2, $macht));
} else {
    $correctie = 0;
}

//resultaat uitspugen, positief dan wel negatief
    if ($g4 < 0){
//  echo ' =  EUR -' . number_format(round($euro+$correctie)/100,2,',','.').'<br>';
    return '-' . round($euro+$correctie)/100;
    } else {
//  echo ' = EUR '.number_format(round($euro+$correctie)/100,2,',','.').'<br>';
    return round($euro+$correctie);
    }
}

Een aantal voorbeelden met omgerekende waarden (decimaal weergegeven bytes):

0 - 0 - 96 - 64 = EUR 3,50
102 - 102 - -98 - 64 = EUR 4,95
-51 - -52 - -84 - 63 = EUR 1,35
0 - 0 - -128 - 63 = EUR 1,00
-61 - -11 - -40 - 64 = EUR 6,78
31 - -123 - 107 - 63 = EUR 0,92
-41 - -93 - -80 - 63 = EUR 1,38
31 - -123 - -21 - 63 = EUR 1,84
51 - 51 - 19 - 64 = EUR 2,30
-41 - -93 - 48 - 64 = EUR 2,76
0 - 0 - -40 - 64 = EUR 6,75


Snappen wat ik hier berekend heb en waarom weet ik niet, enkel dat ik zo in alle gevallen op de correcte bedragen uitkom. Dit lijkt me niet helemaal overeen te komen met IEEE 754.


Daarbij zit dit systeem zo krom in elkaar, kom er nu net achter dat wanneer ik een verkoopprijs van 7 cent heb, daarbij stel dat ik 50% korting krijg als inkoopprijs, vervolgens 4 cent per exemplaar inkoop betaal (correct).
Wanneer ik vervolgens een bedrag van 3,5 cent aan BTW berekenen moet wordt dit 3 cent. (fout)

Wanneer ik een verkoopprijs van 21 cent heb, daarbij stel dat ik 50% korting krijg als inkoopprijs, vervolgens 10 cent per exemplaar inkoop betaal (fout).
Wanneer ik vervolgens een bedrag van 10,5 cent aan BTW berekenen moet wordt dit 11 cent. (correct)

Daarnaast zijn er ook legio gevallen waarbij zowel de in/verkoopprijs correct afgerond wordt, waarbij tevens de BTW op verkoop facturen correct berekend wordt. Of waarbij geen van beide kloppen.
BTW op inkoop facturen komt overigens ook niet overeen met de BTW op verkoop facturen. Het lijkt dus telkens om een andere manier van afronden te gaan, scheelt het dat ik enkel de BTW op verkoop facturen wil reproduceren.

[ Voor 89% gewijzigd door JDVB op 15-10-2012 14:53 ]

Ik ben geen recruiter ofzo, maar wel op zoek naar een collega devver. Typescript/Node/Angular/etc en liefst op HBO niveau. We zitten op een prachtige locatie tussen bos en heide op de Utrechtse heuvelrug. Mijn PM box staat open!

Pagina: 1