ZAČÁTKYNÁVODYOOPDOKUMENTACE
教程/
数学

PHP中的计算器:将数学表达式作为字符串处理

16. 02. 2020

Obsah článku

想象一下,你面临着处理一个简单的数学例子的任务,这个例子是用户以文本字符串的形式输入的,例如,输入一个搜索框。通常情况下,用户想对数字进行简单的数字运算。这篇文章描述了思维过程和具体的操作说明。

天真的执行

很长时间以来,我一直在想,一个简单的数学表达式是否可以通过一些技巧来处理,使代码尽可能的简短......多年后,我真的有了解决方案。

考虑到所给的解决方案只作为一个例子,因为它是极其危险的,一个不诚实的用户可以很容易地在字符串下划线,例如,这将删除整个应用程序或窃取数据库!

// 用户查询
$query = '5 + 3 * 2';
// 将表达式处理为常规的PHP代码
eval('$result = @(' . $query . ');');
//列出变量与表达式的解决方案
echo $result; //打印出11

诀窍在于,eval()函数会像在PHP代码的上下文中一样执行字符串。这很疯狂,但它很有效。该包装器抑制了错误信息。

处理更复杂的输入

除了通过eval()处理表达式是非常危险的之外,它也没有提供足够雄辩的语法来适应每个人。如果用户犯了哪怕一个语法错误,整个表达式将无法被处理。

因此,解决方案是先根据形式方面**理解并纠正用户的查询(称为规范化到规范形式),然后再进一步传递和处理。

我过去曾为QueryNormalizer编程,正是为了这项任务。

处理本身是一项非常具有挑战性的任务,因为你需要正确理解不同的语境。例如,圆括号表示嵌套的块,必须进行递归评估。例如,表达式5+2^(1+3/2)不能直接求解,因为必须先求解分数,将其加到括号内的数字上,然后求解整数幂,最后在底层加。

甚至为了能够满足这个苛刻的要求,表达式不能再被当作普通的字符串,我们需要抽象的层次。从本质上讲,数学是一种描述运算和数字之间关系的语言,因为我们必须处理运算符的优先级、不同的含义、上下文、递归,甚至是数据类型。这就是查询标记化过程**的地方。

我从2015年开始研究数学标记化的问题,并从那时起写了几个不同的解析器。

其中最好的,目前为新的Mathematicator提供动力的,是可在GitHub上开放源代码

标记化的意义在于解析一个字符串,将其分成已知类型的小字符串组,然后将这些字符串转换成对象(数据类型)。然后,转换后的对象数组被聪明的逻辑转换为二进制树,可以描述依赖关系和递归。这是一个非常苛刻的过程,因为有数百种可能的情况,而且用户在查询时可以非常有创意。

令牌数组的主要优点是它可以非常容易地传递给下一层,例如进行实际计算,或将树重绘成LaTeX

使用方法可以看起来很优雅,像这样。

$tokenizer = new Tokenizer(/* 一些依赖性 */);
// 将数学公式转换为代币数组。
$tokens = $tokenizer->tokenize('(5+3)*(2/(7+3))');
// 现在你可以把令牌转换成更有用的格式。
$objectTokens = $tokenizer->tokensToObject($tokens);
dump($objectTokens); // 返回带有元数据的类型化标记
// 渲染到LaTeX
echo $tokenizer->tokensToLatex($objectTokens);
// 渲染到调试树(速度极快)。
echo $tokenizer->renderTokensTree($objectTokens);

查看程序

计算时,程序会显示程序,以显示它是如何做到的,相当多的用户会对此表示赞赏。这实际上对程序员也很有用,因为至少他可以很容易地找出计算中的错误之处,并相应地纠正该算法。当你把所有这些与基于自动测试的机器学习结合起来时,你会得到一些令人惊奇的东西。

看看QueryNormalizer是如何理解你的查询,将数据传递给tokenizer,它根据查询渲染成LaTeX,然后将对象树传递给计算器,计算器返回总体结果。

Příklad: 5+2^(1+3/2).

程序的表示方法是由计算器遍历输入树并根据它所包含的标记和规则一次评估一条规则来实现的。当任何规则被评估时,它将步骤信息放入一个数组。偶尔,一个步骤可能会被证明是不正确的,我们必须回去采取不同的计算路径,但这背后有相当多的魔法,这将暂时隐藏起来,你可以在实现中研究它。

总结

上述程序描述了如何优雅地处理数学表达式,其中我们有数字、运算和与它们的关系。例如,这种方法不能修改表达式或解方程,但我们下次再看这个问题。

*如果你有其他关于如何有效处理数学的想法,我很乐意听取你的意见。

Jan Barášek   Více o autorovi

Autor článku pracuje jako seniorní vývojář a software architekt v Praze. Navrhuje a spravuje velké webové aplikace, které znáte a používáte. Od roku 2009 nabral bohaté zkušenosti, které tímto webem předává dál.

Rád vám pomůžu:

Související články

1.