final public function divRound(string $a, string $b, int $roundingMode) : string
    {
        [$quotient, $remainder] = $this->divQR($a, $b);

        $hasDiscardedFraction = ($remainder !== '0');
        $isPositiveOrZero = ($a[0] === '-') === ($b[0] === '-');

        $discardedFractionSign = function() use ($remainder, $b) : int {
            $r = $this->abs($this->mul($remainder, '2'));
            $b = $this->abs($b);

            return $this->cmp($r, $b);
        };

        $increment = false;

        switch ($roundingMode) {
            case RoundingMode::UNNECESSARY:
                if ($hasDiscardedFraction) {
                    throw RoundingNecessaryException::roundingNecessary();
                }
                break;

            case RoundingMode::UP:
                $increment = $hasDiscardedFraction;
                break;

            case RoundingMode::DOWN:
                break;

            case RoundingMode::CEILING:
                $increment = $hasDiscardedFraction && $isPositiveOrZero;
                break;

            case RoundingMode::FLOOR:
                $increment = $hasDiscardedFraction && ! $isPositiveOrZero;
                break;

            case RoundingMode::HALF_UP:
                $increment = $discardedFractionSign() >= 0;
                break;

            case RoundingMode::HALF_DOWN:
                $increment = $discardedFractionSign() > 0;
                break;

            case RoundingMode::HALF_CEILING:
                $increment = $isPositiveOrZero ? $discardedFractionSign() >= 0 : $discardedFractionSign() > 0;
                break;

            case RoundingMode::HALF_FLOOR:
                $increment = $isPositiveOrZero ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0;
                break;

            case RoundingMode::HALF_EVEN:
                $lastDigit = (int) $quotient[-1];
                $lastDigitIsEven = ($lastDigit % 2 === 0);
                $increment = $lastDigitIsEven ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0;
                break;

            default:
                throw new \InvalidArgumentException('Invalid rounding mode.');
        }

        if ($increment) {
            return $this->add($quotient, $isPositiveOrZero ? '1' : '-1');
        }

        return $quotient;
    }
final public function divRound(string $a, string $b, int $roundingMode) : string
    {
        [$quotient, $remainder] = $this->divQR($a, $b);

        $hasDiscardedFraction = ($remainder !== '0');
        $isPositiveOrZero = ($a[0] === '-') === ($b[0] === '-');

        $discardedFractionSign = function() use ($remainder, $b) : int {
            $r = $this->abs($this->mul($remainder, '2'));
            $b = $this->abs($b);

            return $this->cmp($r, $b);
        };

        $increment = false;

        switch ($roundingMode) {
            case RoundingMode::UNNECESSARY:
                if ($hasDiscardedFraction) {
                    throw RoundingNecessaryException::roundingNecessary();
                }
                break;

            case RoundingMode::UP:
                $increment = $hasDiscardedFraction;
                break;

            case RoundingMode::DOWN:
                break;

            case RoundingMode::CEILING:
                $increment = $hasDiscardedFraction && $isPositiveOrZero;
                break;

            case RoundingMode::FLOOR:
                $increment = $hasDiscardedFraction && ! $isPositiveOrZero;
                break;

            case RoundingMode::HALF_UP:
                $increment = $discardedFractionSign() >= 0;
                break;

            case RoundingMode::HALF_DOWN:
                $increment = $discardedFractionSign() > 0;
                break;

            case RoundingMode::HALF_CEILING:
                $increment = $isPositiveOrZero ? $discardedFractionSign() >= 0 : $discardedFractionSign() > 0;
                break;

            case RoundingMode::HALF_FLOOR:
                $increment = $isPositiveOrZero ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0;
                break;

            case RoundingMode::HALF_EVEN:
                $lastDigit = (int) $quotient[-1];
                $lastDigitIsEven = ($lastDigit % 2 === 0);
                $increment = $lastDigitIsEven ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0;
                break;

            default:
                throw new \InvalidArgumentException('Invalid rounding mode.');
        }

        if ($increment) {
            return $this->add($quotient, $isPositiveOrZero ? '1' : '-1');
        }

        return $quotient;
    }
final public function divRound ( string $ a , string $ b , int $ roundingMode ) : string { [ $ quotient , $ remainder ] = $ this -> divQR ( $ a , $ b ) ; $ hasDiscardedFraction = ( $ remainder !== '0' ) ; $ isPositiveOrZero = ( $ a [ 0 ] === '-' ) === ( $ b [ 0 ] === '-' ) ; $ discardedFractionSign = function ( ) use ( $ remainder , $ b ) : int { $ r = $ this -> abs ( $ this -> mul ( $ remainder , '2' ) ) ; $ b = $ this -> abs ( $ b ) ; return $ this -> cmp ( $ r , $ b ) ; } ; $ increment = false ; switch ( $ roundingMode ) { case RoundingMode :: UNNECESSARY : if ( $ hasDiscardedFraction ) { throw RoundingNecessaryException :: roundingNecessary ( ) ; } break ; case RoundingMode :: UP : $ increment = $ hasDiscardedFraction ; break ; case RoundingMode :: DOWN : break ; case RoundingMode :: CEILING : $ increment = $ hasDiscardedFraction && $ isPositiveOrZero ; break ; case RoundingMode :: FLOOR : $ increment = $ hasDiscardedFraction && ! $ isPositiveOrZero ; break ; case RoundingMode :: HALF_UP : $ increment = $ discardedFractionSign ( ) >= 0 ; break ; case RoundingMode :: HALF_DOWN : $ increment = $ discardedFractionSign ( ) > 0 ; break ; case RoundingMode :: HALF_CEILING : $ increment = $ isPositiveOrZero ? $ discardedFractionSign ( ) >= 0 : $ discardedFractionSign ( ) > 0 ; break ; case RoundingMode :: HALF_FLOOR : $ increment = $ isPositiveOrZero ? $ discardedFractionSign ( ) > 0 : $ discardedFractionSign ( ) >= 0 ; break ; case RoundingMode :: HALF_EVEN : $ lastDigit = ( int ) $ quotient [ - 1 ] ; $ lastDigitIsEven = ( $ lastDigit % 2 === 0 ) ; $ increment = $ lastDigitIsEven ? $ discardedFractionSign ( ) > 0 : $ discardedFractionSign ( ) >= 0 ; break ; default : throw new \ InvalidArgumentException ( 'Invalid rounding mode.' ) ; } if ( $ increment ) { return $ this -> add ( $ quotient , $ isPositiveOrZero ? '1' : '-1' ) ; } return $ quotient ; }
Performs a rounded division.

Rounding is performed when the remainder of the division is not zero.

@param string $a            The dividend.
@param string $b            The divisor.
@param int    $roundingMode The rounding mode.

@return string

@throws \InvalidArgumentException  If the rounding mode is invalid.
@throws RoundingNecessaryException If RoundingMode::UNNECESSARY is provided but rounding is necessary.
Performs a rounded division .