当然ですが、 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 );