Recent Changes - Search:

Hauptmenue (edit)

Php /

BaseConvert

<< | PhpSchnipsel | DoppelPostVerhindern >>

Inhaltsverzeichnis:

Vermutlich kennt ja jeder die schöne Funktion: base_convert(), oder? Leider ist diese etwas begrenzt..

  • Kein Vorzeichen
  • Klappt nur bis zur Basis 36
  • Bei großen Zahlen kommen falsche Ergebnisse

Die "falschen Ergebnisse", ohne Warnung, sind eine bittere Pille. Der hier vorgestellte Konverter ist aufrufkompatibel zum Original, bis auf:

  • schleppt Vorzeichen mit
  • arbeitet bis zur Zahlenbasis 62
  • liefert IMMER korrekte Ergebnisse oder eine Fehlermeldung
function bc_base_convert($value,$quellformat,$zielformat)
{
  $vorrat = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  if(max($quellformat,$zielformat) > strlen($vorrat))
      trigger_error('Bad Format max: '.strlen($vorrat),E_USER_ERROR);
  if(min($quellformat,$zielformat) < 2)
      trigger_error('Bad Format min: 2',E_USER_ERROR);
  $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) trigger_error('Bad Char in input 1',E_USER_ERROR);
    if($wert >= $quellformat) trigger_error('Bad Char in input 2',E_USER_ERROR);
    $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 ;
}

Testcode:

$zahl   = '111111111111111111111111111111111111111111111111111110';
$quelle = 2;
$ziel   = 16;
echo bc_base_convert($zahl,$quelle,$ziel).'<br>';

Am Rande:

Binär: '111111111111111111111111111111111111111111111111111110' ist die größte Zahl, mit der das Original noch korrekt arbeitet.


Der Turbo:

function bccache_base_convert(&$value,$quellformat,$zielformat,$max=1000)
{
  static $cache = array();
  if(count($cache)>$max) array_shift($cache); // begrenzen
  $cache_key = "$value|$quellformat|$zielformat" ;
  if(!isset($cache[$cache_key]))
   $cache[$cache_key] = bc_base_convert($value,$quellformat,$zielformat);
  return $cache[$cache_key];
}

In $max kann man die Anzahl Elemente im Cache angeben. Irgendwie muß man den Speicherverbrauch ja in Grenzen halten...

<< | PhpSchnipsel | DoppelPostVerhindern >>

Edit - History - Print - Recent Changes - Search
Page last modified on November 04, 2007, at 10:10 PM