View source
<?php
namespace Drupal\fraction;
class Fraction implements FractionInterface {
protected $numerator;
protected $denominator;
public function __construct($numerator = 0, $denominator = 1) {
$this
->setNumerator($numerator);
$this
->setDenominator($denominator);
}
public function fromDecimal($value) {
@trigger_error(__METHOD__ . ' is deprecated in drupal:8.0.0 and is removed in drupal:9.0.0. Use the static \\Drupal\\fraction\\Fraction::createFromDecimal() instead.', E_USER_DEPRECATED);
return self::createFromDecimal($value);
}
public static function createFromDecimal($value) {
$precision = strlen(substr(strrchr($value, '.'), 1));
if (function_exists('bcpow')) {
$denominator = bcpow(10, $precision);
}
else {
$denominator = pow(10, $precision);
}
if (function_exists('bcmul')) {
$numerator = bcmul($value, $denominator, 0);
}
else {
$numerator = $value * $denominator;
}
return new Fraction($numerator, $denominator);
}
public function setNumerator($value) {
$this->numerator = (string) $value;
return $this;
}
public function setDenominator($value) {
if (empty($value)) {
$this
->setNumerator(0);
$value = 1;
}
if ($value < 0) {
$numerator = $this
->getNumerator();
$numerator = $numerator * -1;
$this
->setNumerator($numerator);
$value = $value * -1;
}
$this->denominator = (string) $value;
return $this;
}
public function getNumerator() {
return $this->numerator;
}
public function getDenominator() {
return $this->denominator;
}
public function toString(string $separator = '/') {
$numerator = $this
->getNumerator();
$denominator = $this
->getDenominator();
return $numerator . $separator . $denominator;
}
public function toDecimal(int $precision = 0, bool $auto_precision = FALSE) {
$numerator = $this
->getNumerator();
$denominator = $this
->getDenominator();
if ($auto_precision) {
if ($denominator % 10 == 0) {
$max_precision = strlen($denominator) - 1;
}
elseif ($denominator == 1) {
$max_precision = 0;
}
else {
$max_precision = strlen($denominator);
}
$precision = $max_precision > $precision ? $max_precision : $precision;
}
if (function_exists('bcdiv')) {
$value = bcdiv($numerator, $denominator, $precision + 1);
return $this
->bcRound($value, $precision);
}
else {
return (string) round($numerator / $denominator, $precision);
}
}
public function gcd() {
$numerator = $this
->getNumerator();
$denominator = $this
->getDenominator();
$a = str_replace('-', '', $numerator);
$b = str_replace('-', '', $denominator);
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;
}
public function reduce() {
$numerator = $this
->getNumerator();
$denominator = $this
->getDenominator();
$gcd = $this
->gcd();
if (function_exists('bcdiv')) {
$numerator = bcdiv($numerator, $gcd, 0);
$denominator = bcdiv($denominator, $gcd, 0);
}
else {
$numerator = $numerator / $gcd;
$denominator = $denominator / $gcd;
}
$this
->setNumerator($numerator);
$this
->setDenominator($denominator);
return $this;
}
public function reciprocate() {
$numerator = $this
->getDenominator();
$denominator = $this
->getNumerator();
$this
->setNumerator($numerator);
$this
->setDenominator($denominator);
return $this;
}
public function add(Fraction $fraction) {
$numerator1 = $this
->getNumerator();
$denominator1 = $this
->getDenominator();
$numerator2 = $fraction
->getNumerator();
$denominator2 = $fraction
->getDenominator();
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;
}
$this
->setNumerator($numerator);
$this
->setDenominator($denominator);
return $this;
}
public function subtract(Fraction $fraction) {
$numerator1 = $this
->getNumerator();
$denominator1 = $this
->getDenominator();
$numerator2 = $fraction
->getNumerator();
$denominator2 = $fraction
->getDenominator();
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;
}
$this
->setNumerator($numerator);
$this
->setDenominator($denominator);
return $this;
}
public function multiply(Fraction $fraction) {
$numerator1 = $this
->getNumerator();
$denominator1 = $this
->getDenominator();
$numerator2 = $fraction
->getNumerator();
$denominator2 = $fraction
->getDenominator();
if (function_exists('bcmul')) {
$numerator = bcmul($numerator1, $numerator2, 0);
$denominator = bcmul($denominator1, $denominator2, 0);
}
else {
$numerator = $numerator1 * $numerator2;
$denominator = $denominator1 * $denominator2;
}
$this
->setNumerator($numerator);
$this
->setDenominator($denominator);
return $this;
}
public function divide(Fraction $fraction) {
$fraction
->reciprocate();
$numerator1 = $this
->getNumerator();
$denominator1 = $this
->getDenominator();
$numerator2 = $fraction
->getNumerator();
$denominator2 = $fraction
->getDenominator();
if (function_exists('bcmul')) {
$numerator = bcmul($numerator1, $numerator2, 0);
$denominator = bcmul($denominator1, $denominator2, 0);
}
else {
$numerator = $numerator1 * $numerator2;
$denominator = $denominator1 * $denominator2;
}
$this
->setNumerator($numerator);
$this
->setDenominator($denominator);
return $this;
}
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);
}
}