Source of packages/Combie/Math/Bc.php
<?php
/**
* BC Math
*
* Verschiedenste Methoden, um mit groÃÂÃÂen Zahlen zu rechen
*
* @filesource
* @author Combie <uli@combie.de>
* @version $Id$
* @package Combie
* @subpackage Math
*/
namespace Combie\Math;
/**
* BC Math
*
* Rechnen mit unbegrenzter Genauigkeit
* @example packages/Combie/tests/math/test_bc.php
* @package Combie
* @subpackage Math
*/
class Bc
{
/**#@+
* interne Variablen
* @var array Cache
*/
private static $fakutaetcache = array();
private static $basecache = array();
/**#@-*/
/**
* FakultÃÂät
*
* Berechnet rekursiv die FakaltÃÂät von beliebig groÃÂÃÂen Zahlen.
* Um die Berechnungen zu beschleunigen, werden die Zwischenergebnisse
* im Cache gespeichert.
*
* @param string|integer Eine Integer oder BCD Zahl
* @return string FakultÃÂät von Zahl
*/
public static function fakultaet($zahl)
{
if(-1 === bccomp($zahl,2)) return 1;
if(isset(self::$fakutaetcache[$zahl])) return self::$fakutaetcache[$zahl];
self::$fakutaetcache[$zahl] = bcmul($zahl,self::fakultaet(bcsub($zahl,1)));
return self::$fakutaetcache[$zahl];
}
/**
* Base Konverter
*
* Entspricht in etwa der PHP Funktion base_convert()
*
* Erweitert um:
* - Eine Vorzeichenbehandlung
* - Arbeitet bis zur Base 62
* - Zahlenbereich der PHP BC* Funktionen
*
* @param string|integer Eine Integer oder BCD Zahl
* @param integer Basis der Quellzahl 2<=basis<=62
* @param integer Basis des Ergebnisses 2<=basis<=62
* @return string Zur neuen Basis umgewandelte
*/
public static function base_convert($value,$quellformat,$zielformat)
{
$vorrat = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
if(max($quellformat,$zielformat) > strlen($vorrat))
throw new InvalidArgumentException('Bad Format max: '.strlen($vorrat));
if(min($quellformat,$zielformat) < 2)
throw new InvalidArgumentException('Bad Format min: 2');
$dezi = '0';
$level = 0;
$result = '';
$value = trim((string)$value,"\r\n\t +");
$vorzeichen = '-' === $value{0}?'-':'';
$value = ltrim($value,"-0");
$len = strlen($value);
for($i=0;$i<$len;$i++)
{
$wert = strpos($vorrat,$value{$len-1-$i});
if(FALSE === $wert)
throw new InvalidArgumentException('Bad Char in input 1');
if($wert >= $quellformat)
throw new InvalidArgumentException('Bad Char in input 2');
$dezi = bcadd($dezi,bcmul(bcpow($quellformat,$i),$wert));
}
if(10 == $zielformat) return $vorzeichen.$dezi; // abkÃÂürzung
while(1 !== bccomp(bcpow($zielformat,$level++),$dezi));
for($i=$level-2;$i>=0;$i--)
{
$factor = bcpow($zielformat,$i);
$zahl = bcdiv($dezi,$factor,0);
$dezi = bcmod($dezi,$factor);
$result .= $vorrat{$zahl};
}
$result = empty($result)?'0':$result;
return $vorzeichen.$result ;
}
/**
* Cache Base Konverter
*
* Erweitert die Methode base_convert() um einen Cache
*
* @param string|integer Eine Integer oder BCD Zahl
* @param integer Basis der Quellzahl 2<=basis<=62
* @param integer Basis des Ergebnisses 2<=basis<=62
* @param integer Maximale Anzahl Elemente im Cache
* @return string Zur neuen Basis umgewandelte Zahl
*/
public static function cache_base_convert($value,$quellformat,$zielformat,$max=1000)
{
if(count(self::$basecache)>$max) array_shift(self::$basecache); // begrenzen
$cache_key = "$value|$quellformat|$zielformat" ;
if(!isset(self::$basecache[$cache_key]))
self::$basecache[$cache_key] = self::base_convert($value,$quellformat,$zielformat);
return self::$basecache[$cache_key];
}
}
?>