Вход Регистрация
Файл: vendor/brick/math/src/BigRational.php
Строк: 790
<?php

declare(strict_types=1);

namespace 
BrickMath;

use 
BrickMathExceptionDivisionByZeroException;
use 
BrickMathExceptionMathException;
use 
BrickMathExceptionNumberFormatException;
use 
BrickMathExceptionRoundingNecessaryException;

/**
 * An arbitrarily large rational number.
 *
 * This class is immutable.
 *
 * @psalm-immutable
 */
final class BigRational extends BigNumber
{
    
/**
     * The numerator.
     */
    
private BigInteger $numerator;

    
/**
     * The denominator. Always strictly positive.
     */
    
private BigInteger $denominator;

    
/**
     * Protected constructor. Use a factory method to obtain an instance.
     *
     * @param BigInteger $numerator        The numerator.
     * @param BigInteger $denominator      The denominator.
     * @param bool       $checkDenominator Whether to check the denominator for negative and zero.
     *
     * @throws DivisionByZeroException If the denominator is zero.
     */
    
protected function __construct(BigInteger $numeratorBigInteger $denominatorbool $checkDenominator)
    {
        if (
$checkDenominator) {
            if (
$denominator->isZero()) {
                throw 
DivisionByZeroException::denominatorMustNotBeZero();
            }

            if (
$denominator->isNegative()) {
                
$numerator   $numerator->negated();
                
$denominator $denominator->negated();
            }
        }

        
$this->numerator   $numerator;
        
$this->denominator $denominator;
    }

    
/**
     * Creates a BigRational of the given value.
     *
     * @param BigNumber|int|float|string $value
     *
     * @return BigRational
     *
     * @throws MathException If the value cannot be converted to a BigRational.
     *
     * @psalm-pure
     */
    
public static function of($value) : BigNumber
    
{
        return 
parent::of($value)->toBigRational();
    }

    
/**
     * Creates a BigRational out of a numerator and a denominator.
     *
     * If the denominator is negative, the signs of both the numerator and the denominator
     * will be inverted to ensure that the denominator is always positive.
     *
     * @param BigNumber|int|float|string $numerator   The numerator. Must be convertible to a BigInteger.
     * @param BigNumber|int|float|string $denominator The denominator. Must be convertible to a BigInteger.
     *
     * @return BigRational
     *
     * @throws NumberFormatException      If an argument does not represent a valid number.
     * @throws RoundingNecessaryException If an argument represents a non-integer number.
     * @throws DivisionByZeroException    If the denominator is zero.
     *
     * @psalm-pure
     */
    
public static function nd($numerator$denominator) : BigRational
    
{
        
$numerator   BigInteger::of($numerator);
        
$denominator BigInteger::of($denominator);

        return new 
BigRational($numerator$denominatortrue);
    }

    
/**
     * Returns a BigRational representing zero.
     *
     * @return BigRational
     *
     * @psalm-pure
     */
    
public static function zero() : BigRational
    
{
        
/**
         * @psalm-suppress ImpureStaticVariable
         * @var BigRational|null $zero
         */
        
static $zero;

        if (
$zero === null) {
            
$zero = new BigRational(BigInteger::zero(), BigInteger::one(), false);
        }

        return 
$zero;
    }

    
/**
     * Returns a BigRational representing one.
     *
     * @return BigRational
     *
     * @psalm-pure
     */
    
public static function one() : BigRational
    
{
        
/**
         * @psalm-suppress ImpureStaticVariable
         * @var BigRational|null $one
         */
        
static $one;

        if (
$one === null) {
            
$one = new BigRational(BigInteger::one(), BigInteger::one(), false);
        }

        return 
$one;
    }

    
/**
     * Returns a BigRational representing ten.
     *
     * @return BigRational
     *
     * @psalm-pure
     */
    
public static function ten() : BigRational
    
{
        
/**
         * @psalm-suppress ImpureStaticVariable
         * @var BigRational|null $ten
         */
        
static $ten;

        if (
$ten === null) {
            
$ten = new BigRational(BigInteger::ten(), BigInteger::one(), false);
        }

        return 
$ten;
    }

    
/**
     * @return BigInteger
     */
    
public function getNumerator() : BigInteger
    
{
        return 
$this->numerator;
    }

    
/**
     * @return BigInteger
     */
    
public function getDenominator() : BigInteger
    
{
        return 
$this->denominator;
    }

    
/**
     * Returns the quotient of the division of the numerator by the denominator.
     *
     * @return BigInteger
     */
    
public function quotient() : BigInteger
    
{
        return 
$this->numerator->quotient($this->denominator);
    }

    
/**
     * Returns the remainder of the division of the numerator by the denominator.
     *
     * @return BigInteger
     */
    
public function remainder() : BigInteger
    
{
        return 
$this->numerator->remainder($this->denominator);
    }

    
/**
     * Returns the quotient and remainder of the division of the numerator by the denominator.
     *
     * @return BigInteger[]
     */
    
public function quotientAndRemainder() : array
    {
        return 
$this->numerator->quotientAndRemainder($this->denominator);
    }

    
/**
     * Returns the sum of this number and the given one.
     *
     * @param BigNumber|int|float|string $that The number to add.
     *
     * @return BigRational The result.
     *
     * @throws MathException If the number is not valid.
     */
    
public function plus($that) : BigRational
    
{
        
$that BigRational::of($that);

        
$numerator   $this->numerator->multipliedBy($that->denominator);
        
$numerator   $numerator->plus($that->numerator->multipliedBy($this->denominator));
        
$denominator $this->denominator->multipliedBy($that->denominator);

        return new 
BigRational($numerator$denominatorfalse);
    }

    
/**
     * Returns the difference of this number and the given one.
     *
     * @param BigNumber|int|float|string $that The number to subtract.
     *
     * @return BigRational The result.
     *
     * @throws MathException If the number is not valid.
     */
    
public function minus($that) : BigRational
    
{
        
$that BigRational::of($that);

        
$numerator   $this->numerator->multipliedBy($that->denominator);
        
$numerator   $numerator->minus($that->numerator->multipliedBy($this->denominator));
        
$denominator $this->denominator->multipliedBy($that->denominator);

        return new 
BigRational($numerator$denominatorfalse);
    }

    
/**
     * Returns the product of this number and the given one.
     *
     * @param BigNumber|int|float|string $that The multiplier.
     *
     * @return BigRational The result.
     *
     * @throws MathException If the multiplier is not a valid number.
     */
    
public function multipliedBy($that) : BigRational
    
{
        
$that BigRational::of($that);

        
$numerator   $this->numerator->multipliedBy($that->numerator);
        
$denominator $this->denominator->multipliedBy($that->denominator);

        return new 
BigRational($numerator$denominatorfalse);
    }

    
/**
     * Returns the result of the division of this number by the given one.
     *
     * @param BigNumber|int|float|string $that The divisor.
     *
     * @return BigRational The result.
     *
     * @throws MathException If the divisor is not a valid number, or is zero.
     */
    
public function dividedBy($that) : BigRational
    
{
        
$that BigRational::of($that);

        
$numerator   $this->numerator->multipliedBy($that->denominator);
        
$denominator $this->denominator->multipliedBy($that->numerator);

        return new 
BigRational($numerator$denominatortrue);
    }

    
/**
     * Returns this number exponentiated to the given value.
     *
     * @param int $exponent The exponent.
     *
     * @return BigRational The result.
     *
     * @throws InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
     */
    
public function power(int $exponent) : BigRational
    
{
        if (
$exponent === 0) {
            
$one BigInteger::one();

            return new 
BigRational($one$onefalse);
        }

        if (
$exponent === 1) {
            return 
$this;
        }

        return new 
BigRational(
            
$this->numerator->power($exponent),
            
$this->denominator->power($exponent),
            
false
        
);
    }

    
/**
     * Returns the reciprocal of this BigRational.
     *
     * The reciprocal has the numerator and denominator swapped.
     *
     * @return BigRational
     *
     * @throws DivisionByZeroException If the numerator is zero.
     */
    
public function reciprocal() : BigRational
    
{
        return new 
BigRational($this->denominator$this->numeratortrue);
    }

    
/**
     * Returns the absolute value of this BigRational.
     *
     * @return BigRational
     */
    
public function abs() : BigRational
    
{
        return new 
BigRational($this->numerator->abs(), $this->denominatorfalse);
    }

    
/**
     * Returns the negated value of this BigRational.
     *
     * @return BigRational
     */
    
public function negated() : BigRational
    
{
        return new 
BigRational($this->numerator->negated(), $this->denominatorfalse);
    }

    
/**
     * Returns the simplified value of this BigRational.
     *
     * @return BigRational
     */
    
public function simplified() : BigRational
    
{
        
$gcd $this->numerator->gcd($this->denominator);

        
$numerator $this->numerator->quotient($gcd);
        
$denominator $this->denominator->quotient($gcd);

        return new 
BigRational($numerator$denominatorfalse);
    }

    
/**
     * {@inheritdoc}
     */
    
public function compareTo($that) : int
    
{
        return 
$this->minus($that)->getSign();
    }

    
/**
     * {@inheritdoc}
     */
    
public function getSign() : int
    
{
        return 
$this->numerator->getSign();
    }

    
/**
     * {@inheritdoc}
     */
    
public function toBigInteger() : BigInteger
    
{
        
$simplified $this->simplified();

        if (! 
$simplified->denominator->isEqualTo(1)) {
            throw new 
RoundingNecessaryException('This rational number cannot be represented as an integer value without rounding.');
        }

        return 
$simplified->numerator;
    }

    
/**
     * {@inheritdoc}
     */
    
public function toBigDecimal() : BigDecimal
    
{
        return 
$this->numerator->toBigDecimal()->exactlyDividedBy($this->denominator);
    }

    
/**
     * {@inheritdoc}
     */
    
public function toBigRational() : BigRational
    
{
        return 
$this;
    }

    
/**
     * {@inheritdoc}
     */
    
public function toScale(int $scaleint $roundingMode RoundingMode::UNNECESSARY) : BigDecimal
    
{
        return 
$this->numerator->toBigDecimal()->dividedBy($this->denominator$scale$roundingMode);
    }

    
/**
     * {@inheritdoc}
     */
    
public function toInt() : int
    
{
        return 
$this->toBigInteger()->toInt();
    }

    
/**
     * {@inheritdoc}
     */
    
public function toFloat() : float
    
{
        
$simplified $this->simplified();
        return 
$simplified->numerator->toFloat() / $simplified->denominator->toFloat();
    }

    
/**
     * {@inheritdoc}
     */
    
public function __toString() : string
    
{
        
$numerator   = (string) $this->numerator;
        
$denominator = (string) $this->denominator;

        if (
$denominator === '1') {
            return 
$numerator;
        }

        return 
$this->numerator '/' $this->denominator;
    }

    
/**
     * This method is required for serializing the object and SHOULD NOT be accessed directly.
     *
     * @internal
     *
     * @return array{numerator: BigInteger, denominator: BigInteger}
     */
    
public function __serialize(): array
    {
        return [
'numerator' => $this->numerator'denominator' => $this->denominator];
    }

    
/**
     * This method is only here to allow unserializing the object and cannot be accessed directly.
     *
     * @internal
     * @psalm-suppress RedundantPropertyInitializationCheck
     *
     * @param array{numerator: BigInteger, denominator: BigInteger} $data
     *
     * @return void
     *
     * @throws LogicException
     */
    
public function __unserialize(array $data): void
    
{
        if (isset(
$this->numerator)) {
            throw new 
LogicException('__unserialize() is an internal function, it must not be called directly.');
        }

        
$this->numerator $data['numerator'];
        
$this->denominator $data['denominator'];
    }

    
/**
     * This method is required by interface Serializable and SHOULD NOT be accessed directly.
     *
     * @internal
     *
     * @return string
     */
    
public function serialize() : string
    
{
        return 
$this->numerator '/' $this->denominator;
    }

    
/**
     * This method is only here to implement interface Serializable and cannot be accessed directly.
     *
     * @internal
     * @psalm-suppress RedundantPropertyInitializationCheck
     *
     * @param string $value
     *
     * @return void
     *
     * @throws LogicException
     */
    
public function unserialize($value) : void
    
{
        if (isset(
$this->numerator)) {
            throw new 
LogicException('unserialize() is an internal function, it must not be called directly.');
        }

        [
$numerator$denominator] = explode('/'$value);

        
$this->numerator   BigInteger::of($numerator);
        
$this->denominator BigInteger::of($denominator);
    }
}
Онлайн: 0
Реклама