public static function Calculator::round in Commerce Core 8.2
Rounds the given number.
Replicates PHP's support for rounding to the nearest even/odd number even if that number is decimal ($precision > 0).
Parameters
string $number: The number.
int $precision: The number of decimals to round to.
int $mode: The rounding mode. One of the following constants: PHP_ROUND_HALF_UP, PHP_ROUND_HALF_DOWN, PHP_ROUND_HALF_EVEN, PHP_ROUND_HALF_ODD.
Return value
string The rounded number.
Throws
\InvalidArgumentException Thrown when an invalid (non-numeric or negative) precision is given.
2 calls to Calculator::round()
- CalculatorTest::testRounding in modules/
price/ tests/ src/ Unit/ CalculatorTest.php - @covers ::ceil @covers ::floor @covers ::round
- Rounder::round in modules/
price/ src/ Rounder.php - Rounds the given price to its currency precision.
File
- modules/
price/ src/ Calculator.php, line 158
Class
- Calculator
- Provides helpers for bcmath-based arithmetic.
Namespace
Drupal\commerce_priceCode
public static function round(string $number, int $precision = 0, int $mode = PHP_ROUND_HALF_UP) : string {
self::assertNumberFormat($number);
if (!is_numeric($precision) || $precision < 0) {
throw new \InvalidArgumentException('The provided precision should be a positive number');
}
// Round the number in both directions (up/down) before choosing one.
$rounding_increment = bcdiv('1', pow(10, $precision), $precision);
if (self::compare($number, '0') == 1) {
$rounded_up = bcadd($number, $rounding_increment, $precision);
}
else {
$rounded_up = bcsub($number, $rounding_increment, $precision);
}
$rounded_down = bcsub($number, 0, $precision);
// The rounding direction is based on the first decimal after $precision.
$number_parts = explode('.', $number);
$decimals = !empty($number_parts[1]) ? $number_parts[1] : '0';
$relevant_decimal = isset($decimals[$precision]) ? $decimals[$precision] : 0;
if ($relevant_decimal < 5) {
$number = $rounded_down;
}
elseif ($relevant_decimal == 5) {
if ($mode == PHP_ROUND_HALF_UP) {
$number = $rounded_up;
}
elseif ($mode == PHP_ROUND_HALF_DOWN) {
$number = $rounded_down;
}
elseif ($mode == PHP_ROUND_HALF_EVEN) {
$integer = bcmul($rounded_up, pow(10, $precision), 0);
$number = bcmod($integer, '2') == 0 ? $rounded_up : $rounded_down;
}
elseif ($mode == PHP_ROUND_HALF_ODD) {
$integer = bcmul($rounded_up, pow(10, $precision), 0);
$number = bcmod($integer, '2') != 0 ? $rounded_up : $rounded_down;
}
}
elseif ($relevant_decimal > 5) {
$number = $rounded_up;
}
return $number;
}