Inspired by dawidgarus' implementation, here's my simple bc math helper, it does not support function calls, but supports boolean comparisons and is about ~40% faster.
<?php
function bc() {
$argv = func_get_args();
$string = str_replace(' ', '', "({$argv[0]})");
$operations = array();
if (strpos($string, '^') !== false) $operations[] = '\^';
if (strpbrk($string, '*/%') !== false) $operations[] = '[\*\/\%]';
if (strpbrk($string, '+-') !== false) $operations[] = '[\+\-]';
if (strpbrk($string, '<>!=') !== false) $operations[] = '<|>|=|<=|==|>=|!=|<>';
$string = preg_replace('/\$([0-9\.]+)/e', '$argv[$1]', $string);
while (preg_match('/\(([^\)\(]*)\)/', $string, $match)) {
foreach ($operations as $operation) {
if (preg_match("/([+-]{0,1}[0-9\.]+)($operation)([+-]{0,1}[0-9\.]+)/", $match[1], $m)) {
switch($m[2]) {
case '+': $result = bcadd($m[1], $m[3]); break;
case '-': $result = bcsub($m[1], $m[3]); break;
case '*': $result = bcmul($m[1], $m[3]); break;
case '/': $result = bcdiv($m[1], $m[3]); break;
case '%': $result = bcmod($m[1], $m[3]); break;
case '^': $result = bcpow($m[1], $m[3]); break;
case '==':
case '=': $result = bccomp($m[1], $m[3]) == 0; break;
case '>': $result = bccomp($m[1], $m[3]) == 1; break;
case '<': $result = bccomp($m[1], $m[3]) ==-1; break;
case '>=': $result = bccomp($m[1], $m[3]) >= 0; break;
case '<=': $result = bccomp($m[1], $m[3]) <= 0; break;
case '<>':
case '!=': $result = bccomp($m[1], $m[3]) != 0; break;
}
$match[1] = str_replace($m[0], $result, $match[1]);
}
}
$string = str_replace($match[0], $match[1], $string);
}
return $string;
}
?>