У моделі tax/Sales_Total_Quote_Tax
є метод, _deltaRound()
який округляє ціну. Він додає невелику дельту, щоб зупинити недетерміновану поведінку під час округлення 0,5.
/**
* 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;
// 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;
}
Але він зберігає дельту. Якщо він не може знайти таку збережену дельту, вона складає її. Чому? Як я можу сказати, це призводить до різних результатів при однакових операціях.
Скажімо, у нас є $price
3,559, а у нас немає кешу $delta
. Під час проходження методу ми отримаємо $ delta = 0,000001. Тоді ми отримуємо $price
= 3,5595001, що округляє до 3,60, тому у нас є новий $delta
-0,004999. І повертаємо 3.60.
За винятком тепер у нас є дельта, тож давайте зробимо це ще раз, з $price
= 3,559. $price
= 3,5595 - 0,004999 = 3,590001
Що, якщо ми округлимо, отримаємо 3,59. Різні відповіді.
Мені здається, що будь-який використаний алгоритм округлення повинен хоча б давати однакову відповідь кожного разу, коли він запускається з тими ж аргументами, але не цього разу.