这是我为another SO question 编写的一段有点冗长的代码。它确实符合没有eval() 的BOMDAS,但不具备执行复杂/高阶/括号表达式的能力。这种无库方法将表达式分开并系统地减少组件数组,直到删除所有运算符。它当然适用于您的示例表达式:2-1 ;)
-
preg_match() 检查每个运算符的每一侧是否都有一个数字子字符串。
-
preg_split() 将字符串划分为一个由交替的数字和运算符组成的数组。
-
array_search() 查找目标运算符的索引,而它存在于数组中。
-
array_splice() 将 operator 元素及其两侧的元素替换为一个新元素,该元素包含删除的三个元素的数学结果。
** 更新为允许负数 **
代码:(Demo)
$expression = "-11+3*1*4/-6-12";
if (!preg_match('~^-?\d*\.?\d+([*/+-]-?\d*\.?\d+)*$~', $expression)) {
echo "invalid expression";
} else {
$components = preg_split('~(?<=\d)([*/+-])~', $expression, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
var_export($components); // ['-11','+','3','*','1','*','4','/','-6','-','12']
while (($index = array_search('*',$components)) !== false) {
array_splice($components, $index - 1, 3, $components[$index - 1] * $components[$index + 1]);
var_export($components);
// ['-11','+','3','*','4','/','-6','-','12']
// ['-11','+','12','/','-6','-','12']
}
while (($index = array_search('/', $components)) !== false) {
array_splice($components, $index - 1, 3, $components[$index - 1] / $components[$index + 1]);
var_export($components); // [-'11','+','-2','-','12']
}
while (($index = array_search('+', $components)) !== false) {
array_splice($components, $index - 1, 3, $components[$index - 1] + $components[$index + 1]);
var_export($components); // ['-13','-','12']
}
while (($index = array_search('-', $components)) !== false) {
array_splice($components, $index - 1, 3, $components[$index - 1] - $components[$index + 1]);
var_export($components); // [-25]
}
echo current($components); // -25
}
这是a demo of the BOMDAS version,当在两个数字(正数或负数)之间遇到^ 时,它使用php 的pow()。
我不认为我会费心写一个处理括号表达式的版本......但我们会看到我有多无聊。