Why does Magento store a rounding delta when calculating taxes

I have Magento 1.8 on my server and I have checked the _deltaRound() method. It look like this now.

/**
 * Round price based on previous rounding operation delta
 *
 * @param float $price
 * @param string $rate
 * @param bool $direction price including or excluding tax
 * @param string $type
 * @return float
 */
protected function _deltaRound($price, $rate, $direction, $type = 'regular')
{
    if ($price) {
        $rate  = (string) $rate;
        $type  = $type . $direction;
        $delta = isset($this->_roundingDeltas[$type][$rate]) ? $this->_roundingDeltas[$type][$rate] : 0;
        $price += $delta;
        $this->_roundingDeltas[$type][$rate] = $price - $this->_calculator->round($price);
        $price = $this->_calculator->round($price);
    }
    return $price;
}

As you can see, if the _roundingDeltas() is not set, it takes zero as its default value. Its just for noticing you. Magento Team may overhear your doubt. They solved your problem silently. :)

EDIT

Let us analyse the use of this function by applying it into a real time example. Suppose I have a product in cart which is taxable. The quantity that I am going to purchase be, 5. After applying tax, the prdouct has a price $10.5356. So this is my situation

CART
-------
   Product A
       - Price (including tax) - 10.5356
       - Quantity              - 5
       - Tax Rule  - Apply tax for each product. Then calculate the total price according to the quantity purchased.

So now let us calculate the real price that is going to produce in this situation. It will be

  Total =  10.5356 x 5 = 52.678

Now let us assume, magento does not using _deltaRound() method. It just rounds product price upto two decimal places and then calculates total price. In this case, product price will get rounded to 10.54 and hence total price would be

  Total = 10.54 x 5 = 52.7

Now let us assume magento is using _deltaRound() method and this function actually rounds product price to two decimal. Along with that it will keep a delta value, which is in fact the difference between actual price and rounded price, will use for calculating rounded price later. Here enter image description here

  Total =  10.54+10.53+10.54+10.53+10.54 = 52.68

That means _deltaRound() method actually make tax price rounding more accurate to the actual tax pricing. As you stated this method returns different round value depends upon the delta value. This delta value actually makes tax rounding more accurate.

According to this, we can conclude that, as quantity increases, if we are not adopting this method, it will produce a large difference between rounded value and actual value. But if we use this method, it will make our rounded value as close as possible with the actual value.

Magento by default rounds to two decimal places. This is the method that responsible for two decimal places rounding

Location :app/code/core/Mage/Core/Model/Store.php
public function roundPrice($price)
{
    return round($price, 2);
}

If we set it to 4 or something, we can further increase the accuracy of rounding.

Note : This is my openion and overview. It may or may not be true. However it seems accurate and logical for me.

Thanks.


Info

Round price in Magento based on previous rounding operation delta.

app/code/core/Mage/Tax/Model/Sales/Total/Quote/Tax.php:1392 app/code/core/Mage/Tax/Model/Sales/Total/Quote/Subtotal.php:719

protected function _deltaRound($price, $rate, $direction, $type = 'regular')
{
    if ($price) {
        $rate = (string)$rate;
        $type = $type . $direction;
        // initialize the delta to a small number to avoid non-deterministic behavior with rounding of 0.5
        $delta = isset($this->_roundingDeltas[$type][$rate]) ? $this->_roundingDeltas[$type][$rate] : 0.000001;
        $price += $delta;
        $this->_roundingDeltas[$type][$rate] = $price - $this->_calculator->round($price);
        $price = $this->_calculator->round($price);
    }
    return $price;
}

Sometimes this can cause an error due to the high delta calculation error ($this->_calculator->round($price)). For example, for this reason, some prices can vary in the range of ±1 cent.

Solution

To avoid this, you need to improve the accuracy of the delta calculation.

Change

$this->_roundingDeltas[$type][$rate] = $price - $this->_calculator->round($price);

to

$this->_roundingDeltas[$type][$rate] = $price - round($price, 4);

Changes need to be made in both files:

app/code/core/Mage/Tax/Model/Sales/Total/Quote/Tax.php:1392 app/code/core/Mage/Tax/Model/Sales/Total/Quote/Subtotal.php:719

Don't modify or hack core files! Do a rewrite!

The solution was tested on different versions of Magento 1.9.x, but maybe this will work in earlier versions.

P.S.

Change roundPrice function, as shown below, can solve the rounding error problem, but it can cause others (for example, some platforms require rounding up to 2 decimal places).

app/code/core/Mage/Core/Model/Store.php:995

public function roundPrice($price)
{
    return round($price, 4);
}