Question

I allow users to enter prices of products into an inventory, in either NET or Gross. If they enter the price in Gross, the NET is computed for them before being stored and uses the following code:

var vatrate = 12;
IsuppGross = parseInt(suppGross * 100); // makes it an integer

// calc net
var revVR = parseFloat('1.'+vatrate);
Net = ( ( IsuppGross / revVR) / 100 ).toFixed(2);

I struggled to get that working and am not sure if that is where the problem lies.

If I enter '100.00' as a gross figure and my VAT rate is 12%, it returns Net as '112.00', so it seems to be working.

So I enter a product with a Gross price of $100.00 and the net price is computed to be '$89.29' (which I'm assuming to right).

When creating an invoice for 10 of the above items, the bottom of the invoice looks like this:

Net Subtotal $892.90
VAT $107.15
Grand Total $1000.05

What I am expecting is:

Net Subtotal $892.90
VAT $107.10
Grand Total $1000.00

...especially since, when selling just one of the above, results in:

Net Subtotal $89.29
VAT $10.71
Grand Total $100.00

...which expected. It would therefore be reasonable to assume that purchasing 10 of the same items, would cost exactly ten times as much.

Here is the formula I'm using to add the VAT to the Net subtotal:

quantity x net price x 0.12 (10 x 89.29 x 0.12) = 107.148

The above then rounds to 107.15 which when added to the net subtotal is 1000.05.

What formula do I need to arrive at 1000 when I add the VAT back on please?

To Summarize / Clarify This formula... quantity x net price x 0.12 (10 x 89.29 x 0.12)

Gives me 107.148, but what I think I need it to give me is 107.10 instead.

So what javascript function can I used to make that happen (or how do I need to adjust my formula / convert it to code)?

UPDATE @jakub is on the right track I think. I've found an easy way to test it by doing something like:

alert( (892.90 * 0.12).toFixed(2) );  // should equal 107.10

(still equals 107.15)

The above was based on input from Jakub, below. Notice that I'm not multiplying by 10 separately here, because I noticed that we're working at the subtotal level.

Was it helpful?

Solution

One way to do that would be to put rounding at a different place

round(quantity * price) != quantity * round(price)

The same goes for VAT, rounding the result is slightly different from rounding VAT from one product and then multiplying by quantity. Also, you know, that quantity has to be an integer, not a float (if not, it is a different case), so multiplying after rounding should never produce more decimal places.

I hope this helps a little bit.

Ok, to respond to your edit:

You have

(quantity * price * VAT).toFixed(2) = (10 * 89.29 * 0.12).toFixed(2) = (107.148).toFixed(2) = 107.15

You should have

quantity * (price * VAT).toFixed(2) = 10 * (89.29 * 0.12).toFixed(2) = 10 * (10.7148).toFixed(2) = 10 * 10.71 = 107.10

OTHER TIPS

I think I'm correct in saying that the legal position is that the VAT amount invoiced must be the correct percentage of the goods & services invoiced, so one should not sum the VAT-inclusive line-item prices.

One system I worked on which showed VAT per line modified the last line's VAT amount to eliminate rounding errors. They will always be there unless you show your prices with 5 decimal places (assuming you have a VAT rate with 3 significant digits).

Basically the reason for this issue is that the computer is not able to represent most base 10 real numbers using floating point numbers, since the computer uses base 2.

Check this thread: Why not use Double or Float to represent currency?

So one first step is to always use integers for the currency, in this case measured in cents instead of dollars, I presume.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top