W modelu tax/Sales_Total_Quote_Tax
istnieje metoda _deltaRound()
zaokrąglająca cenę. Dodaje małą deltę, aby zatrzymać niedeterministyczne zachowanie podczas zaokrąglania 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;
}
Ale przechowuje deltę. Jeśli nie może znaleźć takiej przechowywanej delty, tworzy ją. Dlaczego? O ile mogę powiedzieć, prowadzi to do różnych wyników przy identycznych operacjach.
Powiedzmy, że mamy $price
3.595 i nie mamy pamięci podręcznej $delta
. Gdy przejdziemy przez tę metodę, otrzymamy deltę = 0,000001. Otrzymujemy wtedy $price
= 3.595001, co zaokrągla do 3,60, więc mamy nową wartość $delta
-0.004999. I zwracamy 3,60.
Z wyjątkiem tego, że mamy deltę, więc zróbmy to jeszcze raz, z $price
= 3.595. $price
= 3,595 - 0,004999 = 3,590001
Co jeśli zaokrąglimy, otrzymamy 3,59. Różne odpowiedzi.
Wydaje mi się, że każdy zastosowany algorytm zaokrąglania powinien przynajmniej dać tę samą odpowiedź za każdym razem, gdy jest uruchamiany z tymi samymi argumentami, ale nie tym razem.