Last update: 31.03.2008 | © 2022 Julian von Mendel | Datenschutz
<?php
/* fractions class
* (C) 2006 Julian von Mendel (http://derjulian.net)
* License: LGPL
*/
class DivisionByZeroException extends Exception{}
class ParametersException extends Exception{}
class fraction
{
public $numerator = 0;
public $denumerator = 1;
function __construct($denumerator=False,$numerator=1,$number=0)
{
if (!$denumerator) return True;
if (is_string($denumerator)) return $this->setstring($denumerator);
if (is_float($denumerator) || is_int($denumerator)) return $this->setdecimal($denumerator);
return $this->set($denumerator,$numerator,$number);
}
public function set($denumerator,$numerator=1,$number=0)
{ /* imports a fraction */
if (is_array($denumerator))
list($denumerator,$numerator,$number) = $denumerator;
$denumerator = (int)$denumerator;
$numerator = (int)$numerator ;
$number = (int)$number ;
if ($denumerator == 0)
throw new DivisionByZeroException("Denumerator can't be zero.");
$this->numerator = $numerator+$number*$denumerator;
$this->denumerator = $denumerator ;
}
public function setdecimal($number)
{ /* imports a decimal fraction */
$number = (float)$number;
$seperated = explode(".",(string)$number);
if (!isset($seperated[1])) $seperated[1] = 0;
$numerator = $seperated[1];
$denumerator = pow(10,strlen($seperated[1]));
$number = $seperated[0];
return $this->set($denumerator,$numerator,$number);
}
public function setstring($string)
{ /* imports a string */
if (substr_count($string," ") == 1)
{
$number = explode(" ",$string );
$string = $number[1] ;
$number = (int)trim($number[0]);
}
else
$number = 0 ;
$fraction = explode("/",$string );
$denumerator = trim($fraction[1] );
$numerator = trim($fraction[0] );
return $this->set($denumerator,$numerator,$number);
}
public function cancel()
{ /* cancels the fraction */
$gcd = math::greatestcommondivisor
(
$this->numerator,
$this->denumerator
);
$this->numerator /= $gcd;
$this->denumerator /= $gcd;
if ($this->denumerator < 0)
{
$this->numerator *= -1;
$this->denumerator = abs($this->denumerator);
}
return True;
}
public static function commondenumerator($fractions)
{ /* calculates a new common denumerator for the given fractions */
if (!is_array($fractions)) throw new WrongParametersException("First parameter has to be an array!");
$values = array();
foreach($fractions as &$fraction)
{
// check wether fraction is an object or a decimal number
if (!is_object($fraction))
{ // if it is a object, convert it to a decimal number
$tmp = $fraction;
$fraction = new self();
$fraction->setdecimal($tmp);
if (!$fraction) throw new WrongParametersException("Fraction isn't a fraction object nor a valid decimal number!");
}
$fraction_ = $fraction->get();
$values[] = $fraction_["denumerator"];
}
$denumerator = math::leastcommonmultiple($values);
foreach($fractions as &$fraction)
$fraction->multipleto($denumerator);
return $fractions;
}
public function multipleby($n)
{ /* multiples the fraction with the given number */
$this->denumerator *= (int)$n;
$this-> numerator *= (int)$n;
return True;
}
public function multipleto($n)
{ /* multiples the fraction with the given number */
if ($n % $this->denumerator != 0) throw new WrongParametersException("The current denumerator MOD the new denumerator must be zero!");
$this->multipleby($n / $this->denumerator);
return True;
}
public static function calculate($fractions,$code_numerator,$code_denumerator=True,$first=False)
{ /* works through all $fractions, where every item in the array can be a
* fraction object or a decimal number, and uses the given $code on them
*/
if (!is_array($fractions)) throw new WrongParametersException("First parameter has to be an array!");
if ($code_denumerator===True) $code_denumerator = $code_numerator;
foreach($fractions as $fraction)
{
// check wether fraction is an object or a decimal number
if (!is_object($fraction))
{ // if it is a object, convert it to a decimal number
$tmp = $fraction;
$fraction = new self();
$fraction->setdecimal($tmp);
if (!$fraction) throw new WrongParametersException("Fraction isn't a fraction object nor a valid decimal number!");
}
// check wether this is the first round
if (!isset($denumerator))
{ // if yes, use the values of the first fraction as initial numbers
extract($fraction->get());
if (!$first) continue;
}
// use the given code to calculate the new fraction
$tmp = $fraction->get();
$current = $tmp["denumerator"];
$new = $denumerator;
eval($code_denumerator);
$denumerator = $new;
$current = $tmp["numerator"];
$new = $numerator;
eval($code_numerator);
$numerator = $new;
}
return new self($denumerator,$numerator);
}
public static function reciprocal($fractions)
{ /* switches numerator and denumerator*/
return self::calculate
(
$fractions ,
"$new = $tmp[\"denumerator\"];",
"$new = $tmp[\"numerator\"];" ,
True
);
}
public static function addition($fractions)
{ /* adds together the given fractions */
$fractions = self::commondenumerator($fractions);
return self::calculate($fractions,"$new += $current;","");
}
public static function substraction($fractions)
{ /* substracts the given fractions */
$fractions = self::commondenumerator($fractions);
return self::calculate($fractions,"$new -= $current;","");
}
public static function multiplication($fractions)
{ /* multiplicates the given fractions */
return self::calculate($fractions,"$new *= $current;");
}
public static function division($fractions)
{ /* divides the given fractions */
return self::calculate($fractions,"$new *= $tmp[\"denumerator\"];","$new *= $tmp[\"numerator\"];");
}
public function getstring($format="%n %f",$fraction_format="%n / %d")
{ /* export fraction as string
public function getstring($format="%n %f",$fraction_format="%n / %d",$html=False)
{ /* export fraction as string
* -------------------------
* $format: you can use the placeholder "%n" which stands for the
* integer in a mixed fraction. "%f" stands for the
* fraction itself. if you don't want a mixed fraction,
* set $format to "%f".
* $fraction_format: placeholder "%n" is replaced by the numerator, "d" by
* the denumerator.
*/
// mixed or non-mixed fraction?
extract($this->get(substr_count($format,"%n") >= 1));
// detect algebraic sign
if ($number == 0) $number = abs($number );
if ($number < 0) $numerator = abs($numerator);
// replace placeholders
$fraction_format = str_replace("%n",$numerator ,$fraction_format);
$fraction_format = str_replace("%d",$denumerator ,$fraction_format);
$format = str_replace("%n",$number ,$format );
$format = str_replace("%f",$fraction_format,$format );
return $format;
}
public function __toString()
{ /* if object is exported as string, return the decimal fraction with two decimals */
return number_format($this->getdecimal(),2);
}
public function get($mixed=False)
{ /* export fraction as array; $mixed specifies if the fraction should be
* mixed
*/
if ($mixed)
{ // mixed fraction
if ($this->numerator / $this->denumerator < 0)
$number = ceil($this->numerator / $this->denumerator);
else
$number = floor($this->numerator / $this->denumerator);
$numerator = $this->numerator % $this->denumerator;
$denumerator = $this->denumerator;
}
else
{ // non-mixed fraction
$number = 0;
$numerator = $this->numerator;
$denumerator = $this->denumerator;
}
return array
(
"denumerator" => $denumerator,
"numerator" => $numerator,
"number" => $number
);
}
public function getdecimal($decimals=2)
{ /* export fraction as decimal fraction */
$number = $this->numerator / $this->denumerator;
return round($number,$decimals);
}
}
?>
© 2009 Julian von Mendel (http://derjulian.net) | Datum: 27.05.2022