当然ですが、 eval() は使いません。
class calculation {
public function __construct() {
}
// 乗算 除算
private function multiplication_division( $interval ) {
while ( preg_match ( '@([-0-9]+)\s*(\*|/)\s*([-0-9]+)@', $interval, $r ) ) {
if ( $r[2] == '*' )
$interval = str_replace ( $r[0], (int) $r[1] * (int) $r[3], $interval );
elseif ( $r[2] == '/' )
$interval = str_replace ( $r[0], (int) $r[1] / (int) $r[3], $interval );
}
return $interval;
}
// 加算 減算
private function addition_subtraction( $interval ) {
while ( preg_match ( '@([-0-9]+)\s*(\+|-)\s*([-0-9]+)@', $interval, $r ) ) {
if ( $r[2] == '+' )
$interval = str_replace ( $r[0], (int) $r[1] + (int) $r[3], $interval );
elseif ( $r[2] == '-' )
$interval = str_replace ( $r[0], (int) $r[1] - (int) $r[3], $interval );
}
return $interval;
}
public function calculation( $interval ) {
while ( preg_match ( '@\(([^\(\)]+)\)@', $interval, $r ) ) {
$formula = $r[1];
$formula = $this->multiplication_division( $formula );
$formula = $this->addition_subtraction( $formula );
$interval = str_replace ( $r[0], $formula, $interval );
}
$interval = $this->multiplication_division( $interval );
$interval = $this->addition_subtraction( $interval );
return $interval;
}
}
$interval = '( ( 2 + 3 - ( 2 * 2 + 6 - 5 ) ) + 10 * 5 / ( 4 - 2 ) ) * 3';
$calc = new calculation;
echo $calc->calculation( $interval );
まずは () の計算を加算&減算→乗算&除算の順番で行います。
() をその計算結果に置き換えています。
while ( preg_match ( '@\(([^\(\)]+)\)@', $interval, $r ) ) {
$formula = $r[1];
$formula = $this->multiplication_division( $formula );
$formula = $this->addition_subtraction( $formula );
$interval = str_replace ( $r[0], $formula, $interval );
}
あとは加算&減算→乗算&除算でおしまいです。
$interval = $this->multiplication_division( $interval );
$interval = $this->addition_subtraction( $interval );


