diff --git a/README.md b/README.md index 60edd9a4..bb51989e 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ Polyfills are provided for: - the `ReflectionConstant` class introduced in PHP 8.4 - the `CURL_HTTP_VERSION_3` and `CURL_HTTP_VERSION_3ONLY` constants introduced in PHP 8.4; - the `grapheme_str_split` function introduced in PHP 8.4; -- the `bcdivmod` function introduced in PHP 8.4; +- the `bcceil`, `bcdivmod`, `bcfloor` and `bcround` functions introduced in PHP 8.4; - the `get_error_handler` and `get_exception_handler` functions introduced in PHP 8.5; - the `NoDiscard` attribute introduced in PHP 8.5; - the `array_first` and `array_last` functions introduced in PHP 8.5; diff --git a/src/Php84/Php84.php b/src/Php84/Php84.php index 1eea63af..3bb387ef 100644 --- a/src/Php84/Php84.php +++ b/src/Php84/Php84.php @@ -205,6 +205,14 @@ public static function grapheme_str_split(string $string, int $length) return $chunks; } + public static function bcceil(string $num): string + { + if (!is_numeric($num)) { + throw new \ValueError('bcceil(): Argument #1 ($num) is not well-formed'); + } + return self::bcround($num, 0, \RoundingMode::PositiveInfinity); + } + public static function bcdivmod(string $num1, string $num2, ?int $scale = null): ?array { if (null === $quot = \bcdiv($num1, $num2, 0)) { @@ -214,4 +222,200 @@ public static function bcdivmod(string $num1, string $num2, ?int $scale = null): return [$quot, \bcmod($num1, $num2, $scale)]; } + + public static function bcfloor(string $num): string + { + if (!is_numeric($num)) { + throw new \ValueError('bcfloor(): Argument #1 ($num) is not well-formed'); + } + return self::bcround($num, 0, \RoundingMode::NegativeInfinity); + } + + /** + * @param \RoundingMode|\RoundingMode::* $mode + */ + public static function bcround(string $num, int $precision = 0, $mode = \RoundingMode::HalfAwayFromZero): string + { + if (!is_numeric($num)) { + throw new \ValueError('bcround(): Argument #1 ($num) is not well-formed'); + } + + $sign = 1; + if ('' !== $num && ('-' === $num[0] || '+' === $num[0])) { + if ('-' === $num[0]) { + $sign = -1; + } + + $num = substr($num, 1); + } + + if (false !== strpos($num, '.')) { + [$intPart, $fracPart] = array_pad(explode('.', $num, 2), 2, ''); + } else { + $intPart = $num; + $fracPart = ''; + } + + if ('' === $intPart) { + $intPart = '0'; + } + + $intPart = self::trimLeadingZeros($intPart); + $fracPart = (string) $fracPart; + + if ($precision >= 0) { + $fracLength = \strlen($fracPart); + + if ($precision <= $fracLength) { + $scaledInt = $intPart.(string) substr($fracPart, 0, $precision); + $scaledFrac = (string) substr($fracPart, $precision); + } else { + $scaledInt = $intPart.$fracPart.str_repeat('0', $precision - $fracLength); + $scaledFrac = ''; + } + } else { + $shift = -$precision; + $intLength = \strlen($intPart); + + if ($shift <= $intLength) { + $splitPos = $intLength - $shift; + $scaledInt = substr($intPart, 0, $splitPos); + $scaledInt = '' === $scaledInt ? '0' : $scaledInt; + $scaledFrac = substr($intPart, $splitPos).$fracPart; + } else { + $scaledInt = '0'; + $scaledFrac = str_repeat('0', $shift - $intLength).$intPart.$fracPart; + } + } + + $roundedInt = self::roundIntegerPart($scaledInt, $scaledFrac, $sign, $mode); + $isZero = '' === trim($roundedInt, '0'); + $absResult = self::formatRoundedDigits($roundedInt, $precision); + + if (-1 === $sign && !$isZero) { + $absResult = '-'.$absResult; + } + + return $absResult; + } + + private static function roundIntegerPart(string $intPart, string $fracPart, int $sign, $mode): string + { + $intPart = self::trimLeadingZeros($intPart); + + if ('' === $fracPart || '' === trim($fracPart, '0')) { + return $intPart; + } + + $firstDigit = $fracPart[0]; + $tail = (string) substr($fracPart, 1); + $tailNonZero = '' !== trim($tail, '0'); + $isGreaterThanHalf = $firstDigit > '5' || ('5' === $firstDigit && $tailNonZero); + $isExactlyHalf = '5' === $firstDigit && !$tailNonZero; + $shouldIncrease = false; + + switch ($mode) { + case \RoundingMode::TowardsZero: + break; + + case \RoundingMode::AwayFromZero: + $shouldIncrease = true; + break; + + case \RoundingMode::PositiveInfinity: + $shouldIncrease = $sign > 0; + break; + + case \RoundingMode::NegativeInfinity: + $shouldIncrease = $sign < 0; + break; + + case \RoundingMode::HalfAwayFromZero: + $shouldIncrease = $isGreaterThanHalf || $isExactlyHalf; + break; + + case \RoundingMode::HalfTowardsZero: + $shouldIncrease = $isGreaterThanHalf; + break; + + case \RoundingMode::HalfEven: + if ($isGreaterThanHalf) { + $shouldIncrease = true; + } elseif ($isExactlyHalf && self::lastDigit($intPart) % 2 === 1) { + $shouldIncrease = true; + } + break; + + case \RoundingMode::HalfOdd: + if ($isGreaterThanHalf) { + $shouldIncrease = true; + } elseif ($isExactlyHalf && self::lastDigit($intPart) % 2 === 0) { + $shouldIncrease = true; + } + break; + } + + if ($shouldIncrease) { + $intPart = self::incrementDigits($intPart); + } + + return self::trimLeadingZeros($intPart); + } + + private static function formatRoundedDigits(string $roundedInt, int $precision): string + { + if ($precision > 0) { + if (\strlen($roundedInt) <= $precision) { + $roundedInt = str_pad($roundedInt, $precision + 1, '0', STR_PAD_LEFT); + } + + $intDigits = substr($roundedInt, 0, -$precision); + $fracDigits = substr($roundedInt, -$precision); + + $intDigits = self::trimLeadingZeros('' === $intDigits ? '0' : $intDigits); + $fracDigits = str_pad($fracDigits, $precision, '0', STR_PAD_LEFT); + + return $intDigits.'.'.$fracDigits; + } + + if (0 === $precision) { + return self::trimLeadingZeros($roundedInt); + } + + $shift = -$precision; + $digits = $roundedInt.str_repeat('0', $shift); + + return self::trimLeadingZeros($digits); + } + + private static function incrementDigits(string $digits): string + { + $digits = '' === $digits ? '0' : $digits; + $index = \strlen($digits) - 1; + $result = $digits; + $carry = 1; + + while ($index >= 0 && $carry) { + $value = ord($result[$index]) - 48 + $carry; + $carry = $value >= 10 ? 1 : 0; + $result[$index] = chr(48 + ($value % 10)); + --$index; + } + + return $carry ? '1'.$result : $result; + } + + private static function trimLeadingZeros(string $digits): string + { + $digits = ltrim($digits, '0'); + + return '' === $digits ? '0' : $digits; + } + + private static function lastDigit(string $digits): int + { + $length = \strlen($digits); + + return $length ? ord($digits[$length - 1]) - 48 : 0; + } } diff --git a/src/Php84/Resources/stubs/RoundingMode.php b/src/Php84/Resources/stubs/RoundingMode.php new file mode 100644 index 00000000..dee28260 --- /dev/null +++ b/src/Php84/Resources/stubs/RoundingMode.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/* +if (\PHP_VERSION_ID >= 80100 && \PHP_VERSION_ID < 80400) { + enum RoundingMode { + case HalfAwayFromZero; // Round to the nearest integer. If the decimal part is 5, round to the integer with the larger absolute value. + case HalfTowardsZero; // Round to the nearest integer. If the decimal part is 5, round to the integer with the smaller absolute value. + case HalfEven; // Round to the nearest integer. If the decimal part is 5, round to the even integer. + case HalfOdd; // Round to the nearest integer. If the decimal part is 5, round to the odd integer. + case TowardsZero; // Round to the nearest integer with a smaller or equal absolute value. + case AwayFromZero; // Round to the nearest integer with a greater or equal absolute value. + case NegativeInfinity; // Round to the largest integer that is smaller or equal. + case PositiveInfinity; // Round to the smallest integer that is greater or equal. + } +} +if (\PHP_VERSION_ID < 80100) { +*/ +if (\PHP_VERSION_ID < 80400) { + // @author Thomas Durand + final class RoundingMode { + const HalfAwayFromZero = 0; // Round to the nearest integer. If the decimal part is 5, round to the integer with the larger absolute value. + const HalfTowardsZero = 1; // Round to the nearest integer. If the decimal part is 5, round to the integer with the smaller absolute value. + const HalfEven = 2; // Round to the nearest integer. If the decimal part is 5, round to the even integer. + const HalfOdd = 3; // Round to the nearest integer. If the decimal part is 5, round to the odd integer. + const TowardsZero = 4; // Round to the nearest integer with a smaller or equal absolute value. + const AwayFromZero = 5; // Round to the nearest integer with a greater or equal absolute value. + const NegativeInfinity = 6; // Round to the largest integer that is smaller or equal. + const PositiveInfinity = 7; // Round to the smallest integer that is greater or equal. + + private function __construct() {} + + public static function cases(): array + { + return [ + self::HalfAwayFromZero, + self::HalfTowardsZero, + self::HalfEven, + self::HalfOdd, + self::TowardsZero, + self::AwayFromZero, + self::NegativeInfinity, + self::PositiveInfinity, + ]; + } + } +} diff --git a/src/Php84/bootstrap.php b/src/Php84/bootstrap.php index 4bd1c17d..416be09d 100644 --- a/src/Php84/bootstrap.php +++ b/src/Php84/bootstrap.php @@ -68,9 +68,21 @@ function mb_rtrim(string $string, ?string $characters = null, ?string $encoding } if (extension_loaded('bcmath')) { + if (!function_exists('bcceil')) { + function bcceil(string $num): string { return p\Php84::bcceil($num); } + } if (!function_exists('bcdivmod')) { function bcdivmod(string $num1, string $num2, ?int $scale = null): ?array { return p\Php84::bcdivmod($num1, $num2, $scale); } } + if (!function_exists('bcfloor')) { + function bcfloor(string $num): string { return p\Php84::bcfloor($num); } + } + if (!function_exists('bcround')) { + /** + * @param \RoundingMode|\RoundingMode::* $mode + */ + function bcround(string $num, int $precision = 0, $mode = RoundingMode::HalfAwayFromZero): string { return p\Php84::bcround($num, $precision, $mode); } + } } if (\PHP_VERSION_ID >= 80200) { diff --git a/tests/Php84/Php84Test.php b/tests/Php84/Php84Test.php index a52901d7..5619d38f 100644 --- a/tests/Php84/Php84Test.php +++ b/tests/Php84/Php84Test.php @@ -760,4 +760,930 @@ public static function bcDivModProvider(): iterable yield ['5', '2', 2, ['2', '1.00']]; yield ['7.2', '3', 2, ['2', '1.20']]; } + + /** + * @dataProvider bcCeilProvider + * + * @requires extension bcmath + */ + public function testBcCeil(string $expected, string $num) + { + $result = \bcceil($num); + $this->assertEquals($expected, $result); + } + + public static function bcCeilProvider(): iterable + { + // Tests cases from https://github.com/php/php-src/blob/php-8.4.4/ext/bcmath/tests/bcceil.phpt + yield ['0', '0']; + yield ['0', '0.00']; + yield ['0', '-0']; + yield ['0', '-0.00']; + yield ['1', '0.01']; + yield ['1', '0.000000000000000000000000000000000000000001']; + yield ['0', '-0.01']; + yield ['0', '-0.000000000000000000000000000000000000000001']; + yield ['1', '1']; + yield ['1', '1.0000']; + yield ['2', '1.0001']; + yield ['100001', '100000.000000000000000000000000000000000000000001']; + yield ['-1', '-1']; + yield ['-1', '-1.0000']; + yield ['-1', '-1.0001']; + yield ['-100000', '-100000.000000000000000000000000000000000000000001']; + } + + /** + * @dataProvider bcCeilProviderError + * + * @requires extension bcmath + */ + public function testBcCeilError(string $num) + { + $this->expectError(); + $this->expectErrorMessage('bcceil(): Argument #1 ($num) is not well-formed'); + \bcceil($num); + } + + public static function bcCeilProviderError(): iterable + { + // Tests cases from https://github.com/php/php-src/blob/php-8.4.4/ext/bcmath/tests/bcceil_error.phpt + yield ['hoge']; + yield ['0.00.1']; + } + + /** + * @dataProvider bcFloorProvider + * + * @requires extension bcmath + */ + public function testBcFloor(string $expected, string $num) + { + $result = \bcfloor($num); + $this->assertEquals($expected, $result); + } + + public static function bcFloorProvider(): iterable + { + // Tests cases from https://github.com/php/php-src/blob/php-8.4.4/ext/bcmath/tests/bcfloor.phpt + yield ['0', '0']; + yield ['0', '0.00']; + yield ['0', '-0']; + yield ['0', '-0.00']; + yield ['0', '0.01']; + yield ['0', '0.000000000000000000000000000000000000000001']; + yield ['-1', '-0.01']; + yield ['-1', '-0.000000000000000000000000000000000000000001']; + yield ['1', '1']; + yield ['1', '1.0000']; + yield ['1', '1.0001']; + yield ['100000', '100000.000000000000000000000000000000000000000001']; + yield ['-1', '-1']; + yield ['-1', '-1.0000']; + yield ['-2', '-1.0001']; + yield ['-100001', '-100000.000000000000000000000000000000000000000001']; + } + + /** + * @dataProvider bcFloorProviderError + * + * @requires extension bcmath + */ + public function testBcFloorError(string $num) + { + $this->expectError(); + $this->expectErrorMessage('bcfloor(): Argument #1 ($num) is not well-formed'); + \bcfloor($num); + } + + public static function bcFloorProviderError(): iterable + { + // Tests cases from https://github.com/php/php-src/blob/php-8.4.4/ext/bcmath/tests/bcfloor_error.phpt + yield ['hoge']; + yield ['0.00.1']; + } + + /** + * @dataProvider bcRoundAllProvider + * + * @requires extension bcmath + */ + public function testBcRoundAll($mode, string $num, string $expected) + { + $result = \bcround($num, 0, $mode); + $this->assertEquals($expected, $result); + } + + public static function bcRoundAllProvider(): iterable + { + // Tests cases from https://github.com/php/php-src/blob/php-8.4.4/ext/bcmath/tests/bcround_all.phpt + yield [\RoundingMode::HalfAwayFromZero, '1.0', '1']; + yield [\RoundingMode::HalfAwayFromZero, '-1.0', '-1']; + yield [\RoundingMode::HalfAwayFromZero, '1.2', '1']; + yield [\RoundingMode::HalfAwayFromZero, '-1.2', '-1']; + yield [\RoundingMode::HalfAwayFromZero, '1.7', '2']; + yield [\RoundingMode::HalfAwayFromZero, '-1.7', '-2']; + yield [\RoundingMode::HalfAwayFromZero, '1.5', '2']; + yield [\RoundingMode::HalfAwayFromZero, '-1.5', '-2']; + yield [\RoundingMode::HalfAwayFromZero, '2.5', '3']; + yield [\RoundingMode::HalfAwayFromZero, '-2.5', '-3']; + yield [\RoundingMode::HalfTowardsZero, '1.0', '1']; + yield [\RoundingMode::HalfTowardsZero, '-1.0', '-1']; + yield [\RoundingMode::HalfTowardsZero, '1.2', '1']; + yield [\RoundingMode::HalfTowardsZero, '-1.2', '-1']; + yield [\RoundingMode::HalfTowardsZero, '1.7', '2']; + yield [\RoundingMode::HalfTowardsZero, '-1.7', '-2']; + yield [\RoundingMode::HalfTowardsZero, '1.5', '1']; + yield [\RoundingMode::HalfTowardsZero, '-1.5', '-1']; + yield [\RoundingMode::HalfTowardsZero, '2.5', '2']; + yield [\RoundingMode::HalfTowardsZero, '-2.5', '-2']; + yield [\RoundingMode::HalfEven, '1.0', '1']; + yield [\RoundingMode::HalfEven, '-1.0', '-1']; + yield [\RoundingMode::HalfEven, '1.2', '1']; + yield [\RoundingMode::HalfEven, '-1.2', '-1']; + yield [\RoundingMode::HalfEven, '1.7', '2']; + yield [\RoundingMode::HalfEven, '-1.7', '-2']; + yield [\RoundingMode::HalfEven, '1.5', '2']; + yield [\RoundingMode::HalfEven, '-1.5', '-2']; + yield [\RoundingMode::HalfEven, '2.5', '2']; + yield [\RoundingMode::HalfEven, '-2.5', '-2']; + yield [\RoundingMode::HalfOdd, '1.0', '1']; + yield [\RoundingMode::HalfOdd, '-1.0', '-1']; + yield [\RoundingMode::HalfOdd, '1.2', '1']; + yield [\RoundingMode::HalfOdd, '-1.2', '-1']; + yield [\RoundingMode::HalfOdd, '1.7', '2']; + yield [\RoundingMode::HalfOdd, '-1.7', '-2']; + yield [\RoundingMode::HalfOdd, '1.5', '1']; + yield [\RoundingMode::HalfOdd, '-1.5', '-1']; + yield [\RoundingMode::HalfOdd, '2.5', '3']; + yield [\RoundingMode::HalfOdd, '-2.5', '-3']; + yield [\RoundingMode::TowardsZero, '1.0', '1']; + yield [\RoundingMode::TowardsZero, '-1.0', '-1']; + yield [\RoundingMode::TowardsZero, '1.2', '1']; + yield [\RoundingMode::TowardsZero, '-1.2', '-1']; + yield [\RoundingMode::TowardsZero, '1.7', '1']; + yield [\RoundingMode::TowardsZero, '-1.7', '-1']; + yield [\RoundingMode::TowardsZero, '1.5', '1']; + yield [\RoundingMode::TowardsZero, '-1.5', '-1']; + yield [\RoundingMode::TowardsZero, '2.5', '2']; + yield [\RoundingMode::TowardsZero, '-2.5', '-2']; + yield [\RoundingMode::AwayFromZero, '1.0', '1']; + yield [\RoundingMode::AwayFromZero, '-1.0', '-1']; + yield [\RoundingMode::AwayFromZero, '1.2', '2']; + yield [\RoundingMode::AwayFromZero, '-1.2', '-2']; + yield [\RoundingMode::AwayFromZero, '1.7', '2']; + yield [\RoundingMode::AwayFromZero, '-1.7', '-2']; + yield [\RoundingMode::AwayFromZero, '1.5', '2']; + yield [\RoundingMode::AwayFromZero, '-1.5', '-2']; + yield [\RoundingMode::AwayFromZero, '2.5', '3']; + yield [\RoundingMode::AwayFromZero, '-2.5', '-3']; + yield [\RoundingMode::NegativeInfinity, '1.0', '1']; + yield [\RoundingMode::NegativeInfinity, '-1.0', '-1']; + yield [\RoundingMode::NegativeInfinity, '1.2', '1']; + yield [\RoundingMode::NegativeInfinity, '-1.2', '-2']; + yield [\RoundingMode::NegativeInfinity, '1.7', '1']; + yield [\RoundingMode::NegativeInfinity, '-1.7', '-2']; + yield [\RoundingMode::NegativeInfinity, '1.5', '1']; + yield [\RoundingMode::NegativeInfinity, '-1.5', '-2']; + yield [\RoundingMode::NegativeInfinity, '2.5', '2']; + yield [\RoundingMode::NegativeInfinity, '-2.5', '-3']; + yield [\RoundingMode::PositiveInfinity, '1.0', '1']; + yield [\RoundingMode::PositiveInfinity, '-1.0', '-1']; + yield [\RoundingMode::PositiveInfinity, '1.2', '2']; + yield [\RoundingMode::PositiveInfinity, '-1.2', '-1']; + yield [\RoundingMode::PositiveInfinity, '1.7', '2']; + yield [\RoundingMode::PositiveInfinity, '-1.7', '-1']; + yield [\RoundingMode::PositiveInfinity, '1.5', '2']; + yield [\RoundingMode::PositiveInfinity, '-1.5', '-1']; + yield [\RoundingMode::PositiveInfinity, '2.5', '3']; + yield [\RoundingMode::PositiveInfinity, '-2.5', '-2']; + } + + /** + * @dataProvider bcRoundAwayFromZeroProvider + * + * @requires extension bcmath + */ + public function testBcRoundAwayFromZero(string $num, int $precision, string $expected) + { + $result = \bcround($num, $precision, \RoundingMode::AwayFromZero); + $this->assertEquals($expected, $result); + } + + public static function bcRoundAwayFromZeroProvider(): iterable + { + // Tests cases from https://github.com/php/php-src/blob/php-8.4.4/ext/bcmath/tests/bcround_away_from_zero.phpt + yield ['1.1', 0, '2']; + yield ['1.2', 0, '2']; + yield ['1.3', 0, '2']; + yield ['1.4', 0, '2']; + yield ['1.6', 0, '2']; + yield ['1.7', 0, '2']; + yield ['1.8', 0, '2']; + yield ['1.9', 0, '2']; + yield ['-1.1', 0, '-2']; + yield ['-1.2', 0, '-2']; + yield ['-1.3', 0, '-2']; + yield ['-1.4', 0, '-2']; + yield ['-1.6', 0, '-2']; + yield ['-1.7', 0, '-2']; + yield ['-1.8', 0, '-2']; + yield ['-1.9', 0, '-2']; + yield ['0', -3, '0']; + yield ['0.01', -3, '1000']; + yield ['-0.01', -3, '-1000']; + yield ['50', -2, '100']; + yield ['-50', -2, '-100']; + yield ['1230', -1, '1230']; + yield ['1235', -1, '1240']; + yield ['-1230', -1, '-1230']; + yield ['-1235', -1, '-1240']; + yield ['3400.0000', -2, '3400']; + yield ['3400.0001', -2, '3500']; + yield ['3450.0000', -2, '3500']; + yield ['3450.0001', -2, '3500']; + yield ['-3400.0000', -2, '-3400']; + yield ['-3400.0001', -2, '-3500']; + yield ['-3450.0000', -2, '-3500']; + yield ['-3450.0001', -2, '-3500']; + yield ['1235', 0, '1235']; + yield ['1235.0', 0, '1235']; + yield ['1235.000001', 0, '1236']; + yield ['1235.5', 0, '1236']; + yield ['1235.500001', 0, '1236']; + yield ['-1235', 0, '-1235']; + yield ['-1235.0', 0, '-1235']; + yield ['-1235.000001', 0, '-1236']; + yield ['-1235.5', 0, '-1236']; + yield ['-1235.500001', 0, '-1236']; + yield ['0.0001', 0, '1']; + yield ['0.5', 0, '1']; + yield ['0.5000', 0, '1']; + yield ['0.5001', 0, '1']; + yield ['-0.0001', 0, '-1']; + yield ['-0.5', 0, '-1']; + yield ['-0.5000', 0, '-1']; + yield ['-0.5001', 0, '-1']; + yield ['28.40', 1, '28.4']; + yield ['28.4000001', 1, '28.5']; + yield ['28.45', 1, '28.5']; + yield ['28.4500001', 1, '28.5']; + yield ['-28.40', 1, '-28.4']; + yield ['-28.4000001', 1, '-28.5']; + yield ['-28.45', 1, '-28.5']; + yield ['-28.4500001', 1, '-28.5']; + yield ['153.90', 1, '153.9']; + yield ['153.9000001', 1, '154.0']; + yield ['153.95', 1, '154.0']; + yield ['153.9500001', 1, '154.0']; + yield ['-153.90', 1, '-153.9']; + yield ['-153.9000001', 1, '-154.0']; + yield ['-153.95', 1, '-154.0']; + yield ['-153.9500001', 1, '-154.0']; + yield ['0.000001', 3, '0.001']; + yield ['0.0005', 3, '0.001']; + yield ['0.000500', 3, '0.001']; + yield ['0.000501', 3, '0.001']; + yield ['-0.000001', 3, '-0.001']; + yield ['-0.0005', 3, '-0.001']; + yield ['-0.000500', 3, '-0.001']; + yield ['-0.000501', 3, '-0.001']; + } + + /** + * @dataProvider bcRoundCeilingProvider + * + * @requires extension bcmath + */ + public function testBcRoundCeiling(string $num, int $precision, string $expected) + { + $result = \bcround($num, $precision, \RoundingMode::PositiveInfinity); + $this->assertEquals($expected, $result); + } + + public static function bcRoundCeilingProvider(): iterable + { + // Tests cases from https://github.com/php/php-src/blob/php-8.4.4/ext/bcmath/tests/bcround_ceiling.phpt + yield ['1.1', 0, '2']; + yield ['1.2', 0, '2']; + yield ['1.3', 0, '2']; + yield ['1.4', 0, '2']; + yield ['1.6', 0, '2']; + yield ['1.7', 0, '2']; + yield ['1.8', 0, '2']; + yield ['1.9', 0, '2']; + yield ['-1.1', 0, '-1']; + yield ['-1.2', 0, '-1']; + yield ['-1.3', 0, '-1']; + yield ['-1.4', 0, '-1']; + yield ['-1.6', 0, '-1']; + yield ['-1.7', 0, '-1']; + yield ['-1.8', 0, '-1']; + yield ['-1.9', 0, '-1']; + yield ['0', -3, '0']; + yield ['0.01', -3, '1000']; + yield ['-0.01', -3, '0']; + yield ['50', -2, '100']; + yield ['-50', -2, '0']; + yield ['1230', -1, '1230']; + yield ['1235', -1, '1240']; + yield ['-1230', -1, '-1230']; + yield ['-1235', -1, '-1230']; + yield ['3400.0000', -2, '3400']; + yield ['3400.0001', -2, '3500']; + yield ['3450.0000', -2, '3500']; + yield ['3450.0001', -2, '3500']; + yield ['-3400.0000', -2, '-3400']; + yield ['-3400.0001', -2, '-3400']; + yield ['-3450.0000', -2, '-3400']; + yield ['-3450.0001', -2, '-3400']; + yield ['1235', 0, '1235']; + yield ['1235.0', 0, '1235']; + yield ['1235.000001', 0, '1236']; + yield ['1235.5', 0, '1236']; + yield ['1235.500001', 0, '1236']; + yield ['-1235', 0, '-1235']; + yield ['-1235.0', 0, '-1235']; + yield ['-1235.000001', 0, '-1235']; + yield ['-1235.5', 0, '-1235']; + yield ['-1235.500001', 0, '-1235']; + yield ['0.0001', 0, '1']; + yield ['0.5', 0, '1']; + yield ['0.5000', 0, '1']; + yield ['0.5001', 0, '1']; + yield ['-0.0001', 0, '0']; + yield ['-0.5', 0, '0']; + yield ['-0.5000', 0, '0']; + yield ['-0.5001', 0, '0']; + yield ['28.40', 1, '28.4']; + yield ['28.4000001', 1, '28.5']; + yield ['28.45', 1, '28.5']; + yield ['28.4500001', 1, '28.5']; + yield ['-28.40', 1, '-28.4']; + yield ['-28.4000001', 1, '-28.4']; + yield ['-28.45', 1, '-28.4']; + yield ['-28.4500001', 1, '-28.4']; + yield ['153.90', 1, '153.9']; + yield ['153.9000001', 1, '154.0']; + yield ['153.95', 1, '154.0']; + yield ['153.9500001', 1, '154.0']; + yield ['-153.90', 1, '-153.9']; + yield ['-153.9000001', 1, '-153.9']; + yield ['-153.95', 1, '-153.9']; + yield ['-153.9500001', 1, '-153.9']; + yield ['0.000001', 3, '0.001']; + yield ['0.0005', 3, '0.001']; + yield ['0.000500', 3, '0.001']; + yield ['0.000501', 3, '0.001']; + yield ['-0.000001', 3, '0.000']; + yield ['-0.0005', 3, '0.000']; + yield ['-0.000500', 3, '0.000']; + yield ['-0.000501', 3, '0.000']; + } + + /** + * @dataProvider bcRoundFloorProvider + * + * @requires extension bcmath + */ + public function testBcRoundFloor(string $num, int $precision, string $expected) + { + $result = \bcround($num, $precision, \RoundingMode::NegativeInfinity); + $this->assertEquals($expected, $result); + } + + public static function bcRoundFloorProvider(): iterable + { + // Tests cases from https://github.com/php/php-src/blob/php-8.4.4/ext/bcmath/tests/bcround_floor.phpt + yield ['1.1', 0, '1']; + yield ['1.2', 0, '1']; + yield ['1.3', 0, '1']; + yield ['1.4', 0, '1']; + yield ['1.6', 0, '1']; + yield ['1.7', 0, '1']; + yield ['1.8', 0, '1']; + yield ['1.9', 0, '1']; + yield ['-1.1', 0, '-2']; + yield ['-1.2', 0, '-2']; + yield ['-1.3', 0, '-2']; + yield ['-1.4', 0, '-2']; + yield ['-1.6', 0, '-2']; + yield ['-1.7', 0, '-2']; + yield ['-1.8', 0, '-2']; + yield ['-1.9', 0, '-2']; + yield ['0', -3, '0']; + yield ['0.01', -3, '0']; + yield ['-0.01', -3, '-1000']; + yield ['50', -2, '0']; + yield ['-50', -2, '-100']; + yield ['1230', -1, '1230']; + yield ['1235', -1, '1230']; + yield ['-1230', -1, '-1230']; + yield ['-1235', -1, '-1240']; + yield ['3400.0000', -2, '3400']; + yield ['3400.0001', -2, '3400']; + yield ['3450.0000', -2, '3400']; + yield ['3450.0001', -2, '3400']; + yield ['-3400.0000', -2, '-3400']; + yield ['-3400.0001', -2, '-3500']; + yield ['-3450.0000', -2, '-3500']; + yield ['-3450.0001', -2, '-3500']; + yield ['1235', 0, '1235']; + yield ['1235.0', 0, '1235']; + yield ['1235.000001', 0, '1235']; + yield ['1235.5', 0, '1235']; + yield ['1235.500001', 0, '1235']; + yield ['-1235', 0, '-1235']; + yield ['-1235.0', 0, '-1235']; + yield ['-1235.000001', 0, '-1236']; + yield ['-1235.5', 0, '-1236']; + yield ['-1235.500001', 0, '-1236']; + yield ['0.0001', 0, '0']; + yield ['0.5', 0, '0']; + yield ['0.5000', 0, '0']; + yield ['0.5001', 0, '0']; + yield ['-0.0001', 0, '-1']; + yield ['-0.5', 0, '-1']; + yield ['-0.5000', 0, '-1']; + yield ['-0.5001', 0, '-1']; + yield ['28.40', 1, '28.4']; + yield ['28.4000001', 1, '28.4']; + yield ['28.45', 1, '28.4']; + yield ['28.4500001', 1, '28.4']; + yield ['-28.40', 1, '-28.4']; + yield ['-28.4000001', 1, '-28.5']; + yield ['-28.45', 1, '-28.5']; + yield ['-28.4500001', 1, '-28.5']; + yield ['153.90', 1, '153.9']; + yield ['153.9000001', 1, '153.9']; + yield ['153.95', 1, '153.9']; + yield ['153.9500001', 1, '153.9']; + yield ['-153.90', 1, '-153.9']; + yield ['-153.9000001', 1, '-154.0']; + yield ['-153.95', 1, '-154.0']; + yield ['-153.9500001', 1, '-154.0']; + yield ['0.000001', 3, '0.000']; + yield ['0.0005', 3, '0.000']; + yield ['0.000500', 3, '0.000']; + yield ['0.000501', 3, '0.000']; + yield ['-0.000001', 3, '-0.001']; + yield ['-0.0005', 3, '-0.001']; + yield ['-0.000500', 3, '-0.001']; + yield ['-0.000501', 3, '-0.001']; + } + + /** + * @dataProvider bcRoundHalfDownProvider + * + * @requires extension bcmath + */ + public function testBcRoundHalfDownFloor(string $num, int $precision, string $expected) + { + $result = \bcround($num, $precision, \RoundingMode::HalfTowardsZero); + $this->assertEquals($expected, $result); + } + + public static function bcRoundHalfDownProvider(): iterable + { + // Tests cases from https://github.com/php/php-src/blob/php-8.4.4/ext/bcmath/tests/bcround_half_down.phpt + yield ['1.1', 0, '1']; + yield ['1.2', 0, '1']; + yield ['1.3', 0, '1']; + yield ['1.4', 0, '1']; + yield ['1.6', 0, '2']; + yield ['1.7', 0, '2']; + yield ['1.8', 0, '2']; + yield ['1.9', 0, '2']; + yield ['-1.1', 0, '-1']; + yield ['-1.2', 0, '-1']; + yield ['-1.3', 0, '-1']; + yield ['-1.4', 0, '-1']; + yield ['-1.6', 0, '-2']; + yield ['-1.7', 0, '-2']; + yield ['-1.8', 0, '-2']; + yield ['-1.9', 0, '-2']; + yield ['0', -3, '0']; + yield ['0.01', -3, '0']; + yield ['-0.01', -3, '0']; + yield ['50', -2, '0']; + yield ['-50', -2, '0']; + yield ['1230', -1, '1230']; + yield ['1235', -1, '1230']; + yield ['-1230', -1, '-1230']; + yield ['-1235', -1, '-1230']; + yield ['3400.0000', -2, '3400']; + yield ['3400.0001', -2, '3400']; + yield ['3450.0000', -2, '3400']; + yield ['3450.0001', -2, '3500']; + yield ['-3400.0000', -2, '-3400']; + yield ['-3400.0001', -2, '-3400']; + yield ['-3450.0000', -2, '-3400']; + yield ['-3450.0001', -2, '-3500']; + yield ['1235', 0, '1235']; + yield ['1235.0', 0, '1235']; + yield ['1235.000001', 0, '1235']; + yield ['1235.5', 0, '1235']; + yield ['1235.500001', 0, '1236']; + yield ['-1235', 0, '-1235']; + yield ['-1235.0', 0, '-1235']; + yield ['-1235.000001', 0, '-1235']; + yield ['-1235.5', 0, '-1235']; + yield ['-1235.500001', 0, '-1236']; + yield ['0.0001', 0, '0']; + yield ['0.5', 0, '0']; + yield ['0.5000', 0, '0']; + yield ['0.5001', 0, '1']; + yield ['-0.0001', 0, '0']; + yield ['-0.5', 0, '0']; + yield ['-0.5000', 0, '0']; + yield ['-0.5001', 0, '-1']; + yield ['28.40', 1, '28.4']; + yield ['28.4000001', 1, '28.4']; + yield ['28.45', 1, '28.4']; + yield ['28.4500001', 1, '28.5']; + yield ['-28.40', 1, '-28.4']; + yield ['-28.4000001', 1, '-28.4']; + yield ['-28.45', 1, '-28.4']; + yield ['-28.4500001', 1, '-28.5']; + yield ['153.90', 1, '153.9']; + yield ['153.9000001', 1, '153.9']; + yield ['153.95', 1, '153.9']; + yield ['153.9500001', 1, '154.0']; + yield ['-153.90', 1, '-153.9']; + yield ['-153.9000001', 1, '-153.9']; + yield ['-153.95', 1, '-153.9']; + yield ['-153.9500001', 1, '-154.0']; + yield ['0.000001', 3, '0.000']; + yield ['0.0005', 3, '0.000']; + yield ['0.000500', 3, '0.000']; + yield ['0.000501', 3, '0.001']; + yield ['-0.000001', 3, '0.000']; + yield ['-0.0005', 3, '0.000']; + yield ['-0.000500', 3, '0.000']; + yield ['-0.000501', 3, '-0.001']; + } + + /** + * @dataProvider bcRoundHalfEvenProvider + * + * @requires extension bcmath + */ + public function testBcRoundHalfEvenFloor(string $num, int $precision, string $expected) + { + $result = \bcround($num, $precision, \RoundingMode::HalfEven); + $this->assertEquals($expected, $result); + } + + public static function bcRoundHalfEvenProvider(): iterable + { + // Tests cases from https://github.com/php/php-src/blob/php-8.4.4/ext/bcmath/tests/bcround_half_even.phpt + yield ['1.1', 0, '1']; + yield ['1.2', 0, '1']; + yield ['1.3', 0, '1']; + yield ['1.4', 0, '1']; + yield ['1.6', 0, '2']; + yield ['1.7', 0, '2']; + yield ['1.8', 0, '2']; + yield ['1.9', 0, '2']; + yield ['-1.1', 0, '-1']; + yield ['-1.2', 0, '-1']; + yield ['-1.3', 0, '-1']; + yield ['-1.4', 0, '-1']; + yield ['-1.6', 0, '-2']; + yield ['-1.7', 0, '-2']; + yield ['-1.8', 0, '-2']; + yield ['-1.9', 0, '-2']; + yield ['0', -3, '0']; + yield ['0.01', -3, '0']; + yield ['-0.01', -3, '0']; + yield ['50', -2, '0']; + yield ['-50', -2, '0']; + yield ['1230', -1, '1230']; + yield ['1235', -1, '1240']; + yield ['-1230', -1, '-1230']; + yield ['-1235', -1, '-1240']; + yield ['3400.0000', -2, '3400']; + yield ['3400.0001', -2, '3400']; + yield ['3450.0000', -2, '3400']; + yield ['3450.0001', -2, '3500']; + yield ['-3400.0000', -2, '-3400']; + yield ['-3400.0001', -2, '-3400']; + yield ['-3450.0000', -2, '-3400']; + yield ['-3450.0001', -2, '-3500']; + yield ['1235', 0, '1235']; + yield ['1235.0', 0, '1235']; + yield ['1235.000001', 0, '1235']; + yield ['1235.5', 0, '1236']; + yield ['1235.500001', 0, '1236']; + yield ['-1235', 0, '-1235']; + yield ['-1235.0', 0, '-1235']; + yield ['-1235.000001', 0, '-1235']; + yield ['-1235.5', 0, '-1236']; + yield ['-1235.500001', 0, '-1236']; + yield ['0.0001', 0, '0']; + yield ['0.5', 0, '0']; + yield ['0.5000', 0, '0']; + yield ['0.5001', 0, '1']; + yield ['-0.0001', 0, '0']; + yield ['-0.5', 0, '0']; + yield ['-0.5000', 0, '0']; + yield ['-0.5001', 0, '-1']; + yield ['28.40', 1, '28.4']; + yield ['28.4000001', 1, '28.4']; + yield ['28.45', 1, '28.4']; + yield ['28.4500001', 1, '28.5']; + yield ['-28.40', 1, '-28.4']; + yield ['-28.4000001', 1, '-28.4']; + yield ['-28.45', 1, '-28.4']; + yield ['-28.4500001', 1, '-28.5']; + yield ['153.90', 1, '153.9']; + yield ['153.9000001', 1, '153.9']; + yield ['153.95', 1, '154.0']; + yield ['153.9500001', 1, '154.0']; + yield ['-153.90', 1, '-153.9']; + yield ['-153.9000001', 1, '-153.9']; + yield ['-153.95', 1, '-154.0']; + yield ['-153.9500001', 1, '-154.0']; + yield ['0.000001', 3, '0.000']; + yield ['0.0005', 3, '0.000']; + yield ['0.000500', 3, '0.000']; + yield ['0.000501', 3, '0.001']; + yield ['-0.000001', 3, '0.000']; + yield ['-0.0005', 3, '0.000']; + yield ['-0.000500', 3, '0.000']; + yield ['-0.000501', 3, '-0.001']; + } + + /** + * @dataProvider bcRoundHalfOddProvider + * + * @requires extension bcmath + */ + public function testBcRoundHalfOddFloor(string $num, int $precision, string $expected) + { + $result = \bcround($num, $precision, \RoundingMode::HalfOdd); + $this->assertEquals($expected, $result); + } + + public static function bcRoundHalfOddProvider(): iterable + { + // Tests cases from https://github.com/php/php-src/blob/php-8.4.4/ext/bcmath/tests/bcround_half_odd.phpt + yield ['1.1', 0, '1']; + yield ['1.2', 0, '1']; + yield ['1.3', 0, '1']; + yield ['1.4', 0, '1']; + yield ['1.6', 0, '2']; + yield ['1.7', 0, '2']; + yield ['1.8', 0, '2']; + yield ['1.9', 0, '2']; + yield ['-1.1', 0, '-1']; + yield ['-1.2', 0, '-1']; + yield ['-1.3', 0, '-1']; + yield ['-1.4', 0, '-1']; + yield ['-1.6', 0, '-2']; + yield ['-1.7', 0, '-2']; + yield ['-1.8', 0, '-2']; + yield ['-1.9', 0, '-2']; + yield ['0', -3, '0']; + yield ['0.01', -3, '0']; + yield ['-0.01', -3, '0']; + yield ['50', -2, '100']; + yield ['-50', -2, '-100']; + yield ['1230', -1, '1230']; + yield ['1235', -1, '1230']; + yield ['-1230', -1, '-1230']; + yield ['-1235', -1, '-1230']; + yield ['3400.0000', -2, '3400']; + yield ['3400.0001', -2, '3400']; + yield ['3450.0000', -2, '3500']; + yield ['3450.0001', -2, '3500']; + yield ['-3400.0000', -2, '-3400']; + yield ['-3400.0001', -2, '-3400']; + yield ['-3450.0000', -2, '-3500']; + yield ['-3450.0001', -2, '-3500']; + yield ['1235', 0, '1235']; + yield ['1235.0', 0, '1235']; + yield ['1235.000001', 0, '1235']; + yield ['1235.5', 0, '1235']; + yield ['1235.500001', 0, '1236']; + yield ['-1235', 0, '-1235']; + yield ['-1235.0', 0, '-1235']; + yield ['-1235.000001', 0, '-1235']; + yield ['-1235.5', 0, '-1235']; + yield ['-1235.500001', 0, '-1236']; + yield ['0.0001', 0, '0']; + yield ['0.5', 0, '1']; + yield ['0.5000', 0, '1']; + yield ['0.5001', 0, '1']; + yield ['-0.0001', 0, '0']; + yield ['-0.5', 0, '-1']; + yield ['-0.5000', 0, '-1']; + yield ['-0.5001', 0, '-1']; + yield ['28.40', 1, '28.4']; + yield ['28.4000001', 1, '28.4']; + yield ['28.45', 1, '28.5']; + yield ['28.4500001', 1, '28.5']; + yield ['-28.40', 1, '-28.4']; + yield ['-28.4000001', 1, '-28.4']; + yield ['-28.45', 1, '-28.5']; + yield ['-28.4500001', 1, '-28.5']; + yield ['153.90', 1, '153.9']; + yield ['153.9000001', 1, '153.9']; + yield ['153.95', 1, '153.9']; + yield ['153.9500001', 1, '154.0']; + yield ['-153.90', 1, '-153.9']; + yield ['-153.9000001', 1, '-153.9']; + yield ['-153.95', 1, '-153.9']; + yield ['-153.9500001', 1, '-154.0']; + yield ['0.000001', 3, '0.000']; + yield ['0.0005', 3, '0.001']; + yield ['0.000500', 3, '0.001']; + yield ['0.000501', 3, '0.001']; + yield ['-0.000001', 3, '0.000']; + yield ['-0.0005', 3, '-0.001']; + yield ['-0.000500', 3, '-0.001']; + yield ['-0.000501', 3, '-0.001']; + } + + /** + * @dataProvider bcRoundHalfUpProvider + * + * @requires extension bcmath + */ + public function testBcRoundHalfUpFloor(string $num, int $precision, string $expected) + { + $result = \bcround($num, $precision, \RoundingMode::HalfAwayFromZero); + $this->assertEquals($expected, $result); + } + + public static function bcRoundHalfUpProvider(): iterable + { + // Tests cases from https://github.com/php/php-src/blob/php-8.4.4/ext/bcmath/tests/bcround_half_up.phpt + yield ['1.1', 0, '1']; + yield ['1.2', 0, '1']; + yield ['1.3', 0, '1']; + yield ['1.4', 0, '1']; + yield ['1.6', 0, '2']; + yield ['1.7', 0, '2']; + yield ['1.8', 0, '2']; + yield ['1.9', 0, '2']; + yield ['-1.1', 0, '-1']; + yield ['-1.2', 0, '-1']; + yield ['-1.3', 0, '-1']; + yield ['-1.4', 0, '-1']; + yield ['-1.6', 0, '-2']; + yield ['-1.7', 0, '-2']; + yield ['-1.8', 0, '-2']; + yield ['-1.9', 0, '-2']; + yield ['0', -3, '0']; + yield ['0.01', -3, '0']; + yield ['-0.01', -3, '0']; + yield ['50', -2, '100']; + yield ['-50', -2, '-100']; + yield ['1230', -1, '1230']; + yield ['1235', -1, '1240']; + yield ['-1230', -1, '-1230']; + yield ['-1235', -1, '-1240']; + yield ['3400.0000', -2, '3400']; + yield ['3400.0001', -2, '3400']; + yield ['3450.0000', -2, '3500']; + yield ['3450.0001', -2, '3500']; + yield ['-3400.0000', -2, '-3400']; + yield ['-3400.0001', -2, '-3400']; + yield ['-3450.0000', -2, '-3500']; + yield ['-3450.0001', -2, '-3500']; + yield ['1235', 0, '1235']; + yield ['1235.0', 0, '1235']; + yield ['1235.000001', 0, '1235']; + yield ['1235.5', 0, '1236']; + yield ['1235.500001', 0, '1236']; + yield ['-1235', 0, '-1235']; + yield ['-1235.0', 0, '-1235']; + yield ['-1235.000001', 0, '-1235']; + yield ['-1235.5', 0, '-1236']; + yield ['-1235.500001', 0, '-1236']; + yield ['0.0001', 0, '0']; + yield ['0.5', 0, '1']; + yield ['0.5000', 0, '1']; + yield ['0.5001', 0, '1']; + yield ['-0.0001', 0, '0']; + yield ['-0.5', 0, '-1']; + yield ['-0.5000', 0, '-1']; + yield ['-0.5001', 0, '-1']; + yield ['28.40', 1, '28.4']; + yield ['28.4000001', 1, '28.4']; + yield ['28.45', 1, '28.5']; + yield ['28.4500001', 1, '28.5']; + yield ['-28.40', 1, '-28.4']; + yield ['-28.4000001', 1, '-28.4']; + yield ['-28.45', 1, '-28.5']; + yield ['-28.4500001', 1, '-28.5']; + yield ['153.90', 1, '153.9']; + yield ['153.9000001', 1, '153.9']; + yield ['153.95', 1, '154.0']; + yield ['153.9500001', 1, '154.0']; + yield ['-153.90', 1, '-153.9']; + yield ['-153.9000001', 1, '-153.9']; + yield ['-153.95', 1, '-154.0']; + yield ['-153.9500001', 1, '-154.0']; + yield ['0.000001', 3, '0.000']; + yield ['0.0005', 3, '0.001']; + yield ['0.000500', 3, '0.001']; + yield ['0.000501', 3, '0.001']; + yield ['-0.000001', 3, '0.000']; + yield ['-0.0005', 3, '-0.001']; + yield ['-0.000500', 3, '-0.001']; + yield ['-0.000501', 3, '-0.001']; + } + + /** + * @dataProvider bcRoundTowardZeroProvider + * + * @requires extension bcmath + */ + public function testBcRoundTowardZeroFloor(string $num, int $precision, string $expected) + { + $result = \bcround($num, $precision, \RoundingMode::TowardsZero); + $this->assertEquals($expected, $result); + } + + public static function bcRoundTowardZeroProvider(): iterable + { + // Tests cases from https://github.com/php/php-src/blob/php-8.4.4/ext/bcmath/tests/bcround_toward_zero.phpt + yield ['1.1', 0, '1']; + yield ['1.2', 0, '1']; + yield ['1.3', 0, '1']; + yield ['1.4', 0, '1']; + yield ['1.6', 0, '1']; + yield ['1.7', 0, '1']; + yield ['1.8', 0, '1']; + yield ['1.9', 0, '1']; + yield ['-1.1', 0, '-1']; + yield ['-1.2', 0, '-1']; + yield ['-1.3', 0, '-1']; + yield ['-1.4', 0, '-1']; + yield ['-1.6', 0, '-1']; + yield ['-1.7', 0, '-1']; + yield ['-1.8', 0, '-1']; + yield ['-1.9', 0, '-1']; + yield ['0', -3, '0']; + yield ['0.01', -3, '0']; + yield ['-0.01', -3, '0']; + yield ['50', -2, '0']; + yield ['-50', -2, '0']; + yield ['1230', -1, '1230']; + yield ['1235', -1, '1230']; + yield ['-1230', -1, '-1230']; + yield ['-1235', -1, '-1230']; + yield ['3400.0000', -2, '3400']; + yield ['3400.0001', -2, '3400']; + yield ['3450.0000', -2, '3400']; + yield ['3450.0001', -2, '3400']; + yield ['-3400.0000', -2, '-3400']; + yield ['-3400.0001', -2, '-3400']; + yield ['-3450.0000', -2, '-3400']; + yield ['-3450.0001', -2, '-3400']; + yield ['1235', 0, '1235']; + yield ['1235.0', 0, '1235']; + yield ['1235.000001', 0, '1235']; + yield ['1235.5', 0, '1235']; + yield ['1235.500001', 0, '1235']; + yield ['-1235', 0, '-1235']; + yield ['-1235.0', 0, '-1235']; + yield ['-1235.000001', 0, '-1235']; + yield ['-1235.5', 0, '-1235']; + yield ['-1235.500001', 0, '-1235']; + yield ['0.0001', 0, '0']; + yield ['0.5', 0, '0']; + yield ['0.5000', 0, '0']; + yield ['0.5001', 0, '0']; + yield ['-0.0001', 0, '0']; + yield ['-0.5', 0, '0']; + yield ['-0.5000', 0, '0']; + yield ['-0.5001', 0, '0']; + yield ['28.40', 1, '28.4']; + yield ['28.4000001', 1, '28.4']; + yield ['28.45', 1, '28.4']; + yield ['28.4500001', 1, '28.4']; + yield ['-28.40', 1, '-28.4']; + yield ['-28.4000001', 1, '-28.4']; + yield ['-28.45', 1, '-28.4']; + yield ['-28.4500001', 1, '-28.4']; + yield ['153.90', 1, '153.9']; + yield ['153.9000001', 1, '153.9']; + yield ['153.95', 1, '153.9']; + yield ['153.9500001', 1, '153.9']; + yield ['-153.90', 1, '-153.9']; + yield ['-153.9000001', 1, '-153.9']; + yield ['-153.95', 1, '-153.9']; + yield ['-153.9500001', 1, '-153.9']; + yield ['0.000001', 3, '0.000']; + yield ['0.0005', 3, '0.000']; + yield ['0.000500', 3, '0.000']; + yield ['0.000501', 3, '0.000']; + yield ['-0.000001', 3, '0.000']; + yield ['-0.0005', 3, '0.000']; + yield ['-0.000500', 3, '0.000']; + yield ['-0.000501', 3, '0.000']; + } }