Skip to content

Commit bba0aba

Browse files
aywankrowinski
authored andcommitted
added half-even rounding (#34)
* added half-even rounding
1 parent 4379ac7 commit bba0aba

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

src/BCMathExtended/BC.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,4 +630,33 @@ public static function bitXor(string $leftOperand, string $rightOperand): string
630630
{
631631
return self::bitOperatorHelper($leftOperand, $rightOperand, self::BIT_OPERATOR_XOR);
632632
}
633+
634+
public static function roundHalfEven(string $number, int $precision = 0): string
635+
{
636+
$number = self::convertScientificNotationToString($number);
637+
if (! self::checkIsFloat($number)) {
638+
return self::checkNumber($number);
639+
}
640+
641+
$precessionPos = strpos($number, '.') + $precision + 1;
642+
if (strlen($number) <= $precessionPos) {
643+
return self::round($number, $precision);
644+
}
645+
646+
if ($number[$precessionPos] !== '5') {
647+
return self::round($number, $precision);
648+
}
649+
650+
$isPrevEven = $number[$precessionPos - 1] === '.'
651+
? (int)$number[$precessionPos - 2] % 2 === 0
652+
: (int)$number[$precessionPos - 1] % 2 === 0
653+
;
654+
$isNegative = self::isNegative($number);
655+
656+
if ($isPrevEven === $isNegative) {
657+
return self::roundUp($number, $precision);
658+
}
659+
660+
return self::roundDown($number, $precision);
661+
}
633662
}

tests/Unit/BCTest.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,47 @@ public function shouldRound($expected, $number, $precision = 0): void
284284
self::assertSame($expected, BC::round((string)$number, $precision));
285285
}
286286

287+
public function roundHalfEvenProvider(): array
288+
{
289+
return [
290+
['2', '1.8'],
291+
['2', '1.5'],
292+
['1', '1.2'],
293+
['1', '0.8'],
294+
['0', '0.5'],
295+
['0', '0.2'],
296+
['-0', '-0.2'],
297+
['0', '-0.5'],
298+
['-1', '-0.8'],
299+
['-1', '-1.2'],
300+
['-2', '-1.5'],
301+
['-2', '-1.8'],
302+
['-2.35', '-2.35', 2],
303+
['-2.4', '-2.35', 1],
304+
['2.4', '2.35', 1],
305+
['0', '0.005', 2],
306+
['0.02', '0.015', 2],
307+
['0.02', '0.025', 2],
308+
['0.04', '0.035', 2],
309+
['0.04', '0.045', 2],
310+
['0.06', '0.055', 2],
311+
['0.06', '0.065', 2],
312+
['0.08', '0.075', 2],
313+
['0.08', '0.085', 2],
314+
];
315+
}
316+
317+
/**
318+
* @test
319+
* @dataProvider roundHalfEvenProvider
320+
* @param string $expected
321+
* @param string $number
322+
* @param int $precision
323+
*/
324+
public function shouldRoundHalfEven(string $expected, string $number, int $precision = 0): void
325+
{
326+
self::assertSame($expected, BC::roundHalfEven($number, $precision));
327+
}
287328

288329
public function randProvider(): array
289330
{

0 commit comments

Comments
 (0)