diff --git a/modules/price/src/Calculator.php b/modules/price/src/Calculator.php index 9f7387d47e..bf7015a358 100644 --- a/modules/price/src/Calculator.php +++ b/modules/price/src/Calculator.php @@ -200,6 +200,31 @@ public static function round($number, $precision = 0, $mode = PHP_ROUND_HALF_UP) return $number; } + /** + * Rounds the given number down to the given precision. + * + * @param string $number + * The number. + * @param int $precision + * The number of decimals to round to. + * + * @return string + * The rounded number. + * + * @throws \InvalidArgumentException + * Thrown when an invalid (non-numeric or negative) precision is given. + */ + public static function roundDown($number, $precision = 0) { + self::assertNumberFormat($number); + if (!is_numeric($precision) || $precision < 0) { + throw new \InvalidArgumentException('The provided precision should be a positive number'); + } + + $base = bcpow(10, $precision); + return self::divide(self::floor(self::multiply($number, $base, self::getPrecision($number))), $base, $precision); + + } + /** * Compares the first number to the second number. * @@ -244,6 +269,23 @@ public static function trim($number) { return $number; } + /** + * Get the precision of a number. + * + * @param string $number + * The number to determine precision. + * + * @return int + * The numbers precision. + */ + public static function getPrecision($number) { + $check = explode('.', $number); + if (!empty($check[1])) { + return strlen($check[1]); + } + return 0; + } + /** * Assert that the given number is a numeric string value. * diff --git a/modules/price/tests/src/Unit/CalculatorTest.php b/modules/price/tests/src/Unit/CalculatorTest.php index e0ab88234c..f7042d97e7 100644 --- a/modules/price/tests/src/Unit/CalculatorTest.php +++ b/modules/price/tests/src/Unit/CalculatorTest.php @@ -44,6 +44,7 @@ public function testComparison() { * @covers ::ceil * @covers ::floor * @covers ::round + * @covers ::roundDown */ public function testRounding() { $this->assertEquals('5', Calculator::ceil('4.4')); @@ -90,6 +91,15 @@ public function testRounding() { foreach ($rounding_data as $item) { $this->assertEquals($item[3], Calculator::round($item[0], $item[1], $item[2])); } + + $this->assertEquals('1.95', Calculator::roundDown('1.95583', 2)); + } + + /** + * @covers ::getPrecision + */ + public function testPrecision() { + $this->assertEquals(2, Calculator::getPrecision('1.99')); } }