-1

I have a shop where the client enters the product price with the tax in his country. When i save it i need to remove the tax and keep only the base.

When i calculate the tax back for the clients from the same country in some cases the total price will be different with 0.01 , 0.03 then the original price.

I tried to calculate with 2 to 4 digits but it never works on all cases.

Ex: price with tax = 157, tax is 7.7% => base = 145.78 and tax amount 11.22

When i calculate the tax to the previous price base i get this:

Base: 145.78 , tax is 7.7% => 11.23 = price is 157.01

Php code i use:

$baseprice = round($fullprice / (1+($taxperc/100)),2);

On the frontend:

$tax = round($baseprice * ( $taxperc / 100 ),2);
$total = $tax + $baseprice;

Anyone have a suggestion about how to fix this ?

Thanks!

Update: after some research I found a solution is to use round with PHP_ROUND_HALF_EVEN

Update2: first solution doesnt work. 1-9 works fine, 10 -tax + tax =10.01

Emanuel
  • 359
  • 4
  • 21
  • Related: https://stackoverflow.com/q/2860432/457268 – k0pernikus Mar 27 '18 at 23:01
  • Possible duplicate of [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – Obsidian Age Mar 27 '18 at 23:04
  • You might also want to use a money library, e.g. http://moneyphp.org/en/latest/ – k0pernikus Mar 27 '18 at 23:05
  • Will check the money library. Thanks – Emanuel Mar 27 '18 at 23:06
  • IMO the Serverside should store both the base price and added tax. Rounding issues will not be avoidable otherwise as to how floats work. – k0pernikus Mar 27 '18 at 23:08
  • I store only the base price because the tax rate changes from time to time, and the old tax will have no use. – Emanuel Mar 27 '18 at 23:09
  • You store only the current base price on the product. Yet on the actual order a buyer bought you then can store both the price and tax applied when bought. Prices and tax rates may change, an order once issued should not. – k0pernikus Mar 27 '18 at 23:12
  • On the order of course I store both, but in the product record i store only the base price. – Emanuel Mar 27 '18 at 23:13

2 Answers2

0

Today's solution would be to work on the back with full number of digits ( for base price, tax and total ) and only when display for user to round it. :)

Emanuel
  • 359
  • 4
  • 21
-1

Seems ( not 100% sure yet, i need to test more ) a solution is to use the banker's rounding PHP_ROUND_HALF_EVEN

$baseprice = round($fullprice / (1+($taxperc/100)),2 , PHP_ROUND_HALF_EVEN);
$tax = round($baseprice * ( $taxperc / 100 ),2 , PHP_ROUND_HALF_EVEN);
$total = $tax + $baseprice;
Emanuel
  • 359
  • 4
  • 21