You are here

class Fraction in Fraction 2.x

Same name in this branch
  1. 2.x src/Fraction.php \Drupal\fraction\Fraction
  2. 2.x src/Element/Fraction.php \Drupal\fraction\Element\Fraction
  3. 2.x src/Plugin/views/filter/Fraction.php \Drupal\fraction\Plugin\views\filter\Fraction
  4. 2.x src/Plugin/views/sort/Fraction.php \Drupal\fraction\Plugin\views\sort\Fraction
  5. 2.x src/Plugin/views/field/Fraction.php \Drupal\fraction\Plugin\views\field\Fraction
Same name and namespace in other branches
  1. 8 src/Fraction.php \Drupal\fraction\Fraction

A simple class for representing and acting upon a fraction.

Hierarchy

Expanded class hierarchy of Fraction

10 files declare their use of Fraction
DecimalFraction.php in src/Plugin/migrate/process/DecimalFraction.php
fraction.module in ./fraction.module
Fraction module code.
Fraction.php in src/Plugin/views/field/Fraction.php
FractionConstraintTest.php in tests/src/Kernel/Plugin/Constraints/FractionConstraintTest.php
FractionDecimal.php in src/Element/FractionDecimal.php

... See full list

4 string references to 'Fraction'
fraction.info.yml in ./fraction.info.yml
fraction.info.yml
fraction.schema.yml in config/schema/fraction.schema.yml
config/schema/fraction.schema.yml
FractionTarget::importTypes in src/Feeds/Target/FractionTarget.php
Helper function to define the ways to import the fraction data.
FractionWidget::formElement in src/Plugin/Field/FieldWidget/FractionWidget.php
Returns the form for a single field widget.

File

src/Fraction.php, line 8

Namespace

Drupal\fraction
View source
class Fraction implements FractionInterface {

  /**
   * Numerator of the fraction.
   *
   * @var string
   */
  protected $numerator;

  /**
   * Denominator of the fraction.
   *
   * @var string
   */
  protected $denominator;

  /**
   * Constructs a Fraction object.
   *
   * @param string|int $numerator
   *   The fraction's numerator. Defaults to 0.
   * @param string|int $denominator
   *   The fraction's denominator. Defaults to 1.
   */
  public function __construct($numerator = 0, $denominator = 1) {
    $this
      ->setNumerator($numerator);
    $this
      ->setDenominator($denominator);
  }

  /**
   * {@inheritdoc}
   */
  public static function createFromDecimal($value) {

    // Calculate the precision by counting the number of decimal places.
    $precision = strlen(substr(strrchr($value, '.'), 1));

    // Create the denominator by raising 10 to the power of the precision.
    if (function_exists('bcpow')) {
      $denominator = bcpow(10, $precision);
    }
    else {
      $denominator = pow(10, $precision);
    }

    // Calculate the numerator by multiplying the value by the denominator.
    if (function_exists('bcmul')) {
      $numerator = bcmul($value, $denominator, 0);
    }
    else {
      $numerator = $value * $denominator;
    }
    return new Fraction($numerator, $denominator);
  }

  /**
   * {@inheritdoc}
   */
  public function setNumerator($value) {

    // Cast the value as a string and save it.
    $this->numerator = (string) $value;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function setDenominator($value) {

    // Protect against division by zero.
    if (empty($value)) {
      $this
        ->setNumerator(0);
      $value = 1;
    }

    // Normalize negative fractions.
    // If the denominator is negative, invert the signs for both numbers.
    if ($value < 0) {
      $numerator = $this
        ->getNumerator();
      $numerator = $numerator * -1;
      $this
        ->setNumerator($numerator);
      $value = $value * -1;
    }

    // Cast the value as a string and save it.
    $this->denominator = (string) $value;
    return $this;
  }

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

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

  /**
   * {@inheritdoc}
   */
  public function toString(string $separator = '/') {

    // Get the numerator and denominator.
    $numerator = $this
      ->getNumerator();
    $denominator = $this
      ->getDenominator();

    // Concatenate with the separator and return.
    return $numerator . $separator . $denominator;
  }

  /**
   * {@inheritdoc}
   */
  public function toDecimal(int $precision = 0, bool $auto_precision = FALSE) {

    // Get the numerator and denominator.
    $numerator = $this
      ->getNumerator();
    $denominator = $this
      ->getDenominator();

    // If auto precision is on figure out the maximum precision.
    if ($auto_precision) {

      // If the denominator is base-10, max precision is the number of zeroes
      // in the denominator.
      if ($denominator % 10 == 0) {
        $max_precision = strlen($denominator) - 1;
      }
      elseif ($denominator == 1) {
        $max_precision = 0;
      }
      else {
        $max_precision = strlen($denominator);
      }

      // Use the greater of the two precisions.
      $precision = $max_precision > $precision ? $max_precision : $precision;
    }

    // Divide the numerator by the denominator (using BCMath if available).
    if (function_exists('bcdiv')) {

      // Divide the numerator and denominator, with extra precision.
      $value = bcdiv($numerator, $denominator, $precision + 1);

      // Return a decimal string rounded to the final precision.
      return $this
        ->bcRound($value, $precision);
    }
    else {
      return (string) round($numerator / $denominator, $precision);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function gcd() {

    // Get the numerator and denominator.
    $numerator = $this
      ->getNumerator();
    $denominator = $this
      ->getDenominator();

    // Make sure both numbers are positive.
    $a = str_replace('-', '', $numerator);
    $b = str_replace('-', '', $denominator);

    // Euclid's algorithm gives us the greatest common divisor.
    // Use BCMath's modulus function if available.
    if (function_exists('bcmod')) {
      while ($b != 0) {
        $t = $b;
        $b = bcmod($a, $b);
        $a = $t;
      }
    }
    else {
      while ($b != 0) {
        $t = $b;
        $b = $a % $b;
        $a = $t;
      }
    }
    return (string) $a;
  }

  /**
   * {@inheritdoc}
   */
  public function reduce() {

    // Get the numerator and denominator.
    $numerator = $this
      ->getNumerator();
    $denominator = $this
      ->getDenominator();

    // Calculate the greatest common divisor.
    $gcd = $this
      ->gcd();

    // Divide the numerator and denominator by the gcd.
    // Use BCMath division if available.
    if (function_exists('bcdiv')) {
      $numerator = bcdiv($numerator, $gcd, 0);
      $denominator = bcdiv($denominator, $gcd, 0);
    }
    else {
      $numerator = $numerator / $gcd;
      $denominator = $denominator / $gcd;
    }

    // Save the numerator and denominator.
    $this
      ->setNumerator($numerator);
    $this
      ->setDenominator($denominator);
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function reciprocate() {

    // Get the numerator and denominator, but flipped.
    $numerator = $this
      ->getDenominator();
    $denominator = $this
      ->getNumerator();

    // Save the numerator and denominator.
    $this
      ->setNumerator($numerator);
    $this
      ->setDenominator($denominator);
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function add(Fraction $fraction) {

    // Get the numerator and denominator of each fraction.
    $numerator1 = $this
      ->getNumerator();
    $denominator1 = $this
      ->getDenominator();
    $numerator2 = $fraction
      ->getNumerator();
    $denominator2 = $fraction
      ->getDenominator();

    // Calculate the sum of the two fractions.
    // Use BCMath if available.
    if (function_exists('bcmul') && function_exists('bcadd')) {
      $denominator = bcmul($denominator1, $denominator2, 0);
      $numerator = bcadd(bcmul($numerator1, $denominator2, 0), bcmul($numerator2, $denominator1, 0), 0);
    }
    else {
      $denominator = $denominator1 * $denominator2;
      $numerator = $numerator1 * $denominator2 + $numerator2 * $denominator1;
    }

    // Save the numerator and denominator.
    $this
      ->setNumerator($numerator);
    $this
      ->setDenominator($denominator);

    // Reduce.
    $this
      ->reduce();
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function subtract(Fraction $fraction) {

    // Get the numerator and denominator of each fraction.
    $numerator1 = $this
      ->getNumerator();
    $denominator1 = $this
      ->getDenominator();
    $numerator2 = $fraction
      ->getNumerator();
    $denominator2 = $fraction
      ->getDenominator();

    // Calculate the difference of the two fractions.
    // Use BCMath if available.
    if (function_exists('bcmul') && function_exists('bcsub')) {
      $denominator = bcmul($denominator1, $denominator2, 0);
      $numerator = bcsub(bcmul($numerator1, $denominator2, 0), bcmul($numerator2, $denominator1, 0), 0);
    }
    else {
      $denominator = $denominator1 * $denominator2;
      $numerator = $numerator1 * $denominator2 - $numerator2 * $denominator1;
    }

    // Save the numerator and denominator.
    $this
      ->setNumerator($numerator);
    $this
      ->setDenominator($denominator);

    // Reduce.
    $this
      ->reduce();
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function multiply(Fraction $fraction) {

    // Get the numerator and denominator of each fraction.
    $numerator1 = $this
      ->getNumerator();
    $denominator1 = $this
      ->getDenominator();
    $numerator2 = $fraction
      ->getNumerator();
    $denominator2 = $fraction
      ->getDenominator();

    // Calculate the product of the two fractions.
    // Use BCMath if available.
    if (function_exists('bcmul')) {
      $numerator = bcmul($numerator1, $numerator2, 0);
      $denominator = bcmul($denominator1, $denominator2, 0);
    }
    else {
      $numerator = $numerator1 * $numerator2;
      $denominator = $denominator1 * $denominator2;
    }

    // Save the numerator and denominator.
    $this
      ->setNumerator($numerator);
    $this
      ->setDenominator($denominator);

    // Reduce.
    $this
      ->reduce();
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function divide(Fraction $fraction) {

    // Reciprocate the fraction.
    $fraction
      ->reciprocate();

    // Get the numerator and denominator of each fraction.
    $numerator1 = $this
      ->getNumerator();
    $denominator1 = $this
      ->getDenominator();
    $numerator2 = $fraction
      ->getNumerator();
    $denominator2 = $fraction
      ->getDenominator();

    // Calculate the quotient of the two fractions.
    // Use BCMath if available.
    if (function_exists('bcmul')) {
      $numerator = bcmul($numerator1, $numerator2, 0);
      $denominator = bcmul($denominator1, $denominator2, 0);
    }
    else {
      $numerator = $numerator1 * $numerator2;
      $denominator = $denominator1 * $denominator2;
    }

    // Save the numerator and denominator.
    $this
      ->setNumerator($numerator);
    $this
      ->setDenominator($denominator);

    // Reduce.
    $this
      ->reduce();
    return $this;
  }

  /**
   * BCMath decimal rounding function.
   *
   * @param $value
   *   The value to round.
   * @param int $precision
   *   The desired decimal precision.
   *
   * @return string
   *   Returns a rounded decimal value, as a PHP string.
   */
  protected function bcRound($value, $precision) {
    if ($value[0] != '-') {
      return bcadd($value, '0.' . str_repeat('0', $precision) . '5', $precision);
    }
    return bcsub($value, '0.' . str_repeat('0', $precision) . '5', $precision);
  }

}

Members

Namesort descending Modifiers Type Description Overrides
Fraction::$denominator protected property Denominator of the fraction.
Fraction::$numerator protected property Numerator of the fraction.
Fraction::add public function Adds another fraction to this one. Overrides FractionInterface::add
Fraction::bcRound protected function BCMath decimal rounding function.
Fraction::createFromDecimal public static function Calculates the numerator and denominator from a decimal value. Overrides FractionInterface::createFromDecimal
Fraction::divide public function Divides this fraction by another one. Overrides FractionInterface::divide
Fraction::gcd public function Calculate the fraction's greatest common divisor using Euclid's algorithm. Overrides FractionInterface::gcd
Fraction::getDenominator public function Gets the denominator. Overrides FractionInterface::getDenominator
Fraction::getNumerator public function Gets the numerator. Overrides FractionInterface::getNumerator
Fraction::multiply public function Multiplies this fraction with another one. Overrides FractionInterface::multiply
Fraction::reciprocate public function Reciprocates the fraction. Overrides FractionInterface::reciprocate
Fraction::reduce public function Reduces the fraction to its simplest form. Overrides FractionInterface::reduce
Fraction::setDenominator public function Sets the denominator. Overrides FractionInterface::setDenominator
Fraction::setNumerator public function Sets the numerator. Overrides FractionInterface::setNumerator
Fraction::subtract public function Subtracts another fraction from this one. Overrides FractionInterface::subtract
Fraction::toDecimal public function Calculates the decimal equivalent of the fraction. Overrides FractionInterface::toDecimal
Fraction::toString public function Return a string representation of the fraction. Overrides FractionInterface::toString
Fraction::__construct public function Constructs a Fraction object.