PHP: parse_expr(PHP >= 4) Berechnet das Ergebnis eines mathematischen Ausdrucks. Beschreibungdouble parse_expr (string string) Diese Funktion das Ergebnis des mathematischen Ausdrucks zurück, oder 0 (null), falls die Berechnung scheiterte. Zahlen müssen mit einen '.' als dezimalpunkt und können auch in exponentialschreiweise eingegeben werden: "1.2e-3 + 0.001". Um die Eingabe zu säuber kann die PHP-Funktion str_replace benutzt werden: parse_expr (str_replace (',','.','1.2e-3 + 0.001'));. Die Ausgabe kann dann wiederum mit str_replace korrigiert werden: str_replace ('.',',',parse_expr (str_replace (',','.','1.2e-3 + 0.001')));. Die Funktion erkennt den Fehler, wenn versucht wird durch 0 (null) zu teilen und gibt IEEE konform 'INF (Division durch 0)' aus. Zu große Zahlen und Ergebnisse werden ebenfalls erkannt und die Funktion gibt 'INF' zurück ('1e200*1e200' wie '1e999' liefern das Ergebnis 'INF'). Um den eingegebenen mathematischen Ausdruck zu berechnen wird eine Technik namens "Rekursiver Abstieg" benutzt. Die Funktion bietet noch Raum für Verbesserungen. So sollte die Eingabe eines falschen Zeichens zu einem kontrollierten Abbruch mit Fehlermeldung führen. '1+x2+3' beispielsweise gibt '1' aus, sollte aber 'NaN (unerlaubtes Zeichen)' zurückgeben. Source Code$mpg = NULL;
function parse_expr ($input)
{
global $mpg;
$mpg = array ('input' => $input."\0"
,'result' => 0 ,'char' => 0
,'i' => -1, 'err' => 0);
$result = mp_ausdruck ();
return empty ($mpg['err']) == true ?
$result : $mpg['err'];
}
function mp_ausdruck ()
{
global $mpg;
$value = mp_term ();
$run = true;
do {
switch ($mpg['char'])
{
case '+':
$value += mp_term ();
break;
case '-':
$value -= mp_term ();
break;
default:
$run = false;
break;
}
} while ($run == true);
return $value;
}
function mp_term ()
{
global $mpg;
$value = mp_faktor ();
$run = true;
do {
switch ($mpg['char'])
{
case '*':
$value *= mp_faktor ();
break;
case '/':
$tmp = mp_faktor ();
if ($tmp != 0)
$value /= $tmp;
else
{
$value = 0;
$mpg['err'] = 'INF (Division durch 0)';
}
break;
default:
$run = false;
break;
}
} while ($run == true);
return $value;
}
function mp_faktor ()
{
global $mpg;
$value = 0;
$mpg['char'] = mp_lies ();
if (('0' <= $mpg['char'] && $mpg['char'] <= '9')
|| $mpg['char'] == '-')
$value = mp_zahl ();
if ($mpg['char'] == '(')
{
$value = mp_ausdruck ();
$mpg['char'] = mp_lies ();
}
return $value;
}
function mp_lies ()
{
static $mp_whitesp = array (' ',"\t","\n","\r");
global $mpg;
do {
$mpg['char'] = $mpg['input'][++$mpg['i']];
} while (in_array ($mpg['char'], $mp_whitesp) == true);
return $mpg['char'];
}
function mp_zahl ()
{
global $mpg;
$starti = $mpg['i'];
if ($mpg['char'] == '-')
$mpg['char'] = mp_lies();
while (true)
{
if (('0' <= $mpg['char'] && $mpg['char'] <= '9')
|| $mpg['char'] == '.')
$mpg['char'] = mp_lies();
else
{
if ($mpg['char'] == 'e' || $mpg['char'] == 'E')
{
++$mpg['i'];
$mpg['char'] = mp_lies();
}
else
break;
}
}
return doubleval (substr (
$mpg['input'], $starti, $mpg['i'] - $starti));
}
Quelle: Entwurf und Umsetzung Frank Olschewski. 12/23/05 |