乐趣区

关于前端:揭秘你处理数据的底层逻辑详解公式引擎计算一

背景

身处信息时代之中,咱们最能显著感触到的一点就是密集数据大量暴发,人们积攒的数据也越来越多。这些庞杂的数据呈现在一起,传统应用的很多数据记录、查问、汇总工具并不能满足人们的需要。更无效的将这些大量数据处理,让计算机听懂人类须要的数据成果,从而造成更加自动化、智能的数据处理形式。

为了解决这些海量数据,呈现了各种大数据引擎、搜索引擎、计算引擎、3D 引擎等,用以更好解决数据庞杂带来人工无奈解决的问题。而作为其中比拟根底的计算公式引擎,是在计算程序中负责对数据进行解决的外围局部。接下来咱们将开展介绍计算引擎的基本原理、计算链和异步函数形成,并从计算公式引擎的基本概念登程,用咱们的表格电子组件作为例子,为大家演示这些内容如何在 JavaScript 中实现。

公式引擎的计算原理

计算引擎负责解决数据起源的统计,数据的操作,数据的治理,并将适合的计算结果依照要求给予返回。针对数据处理的目标不同,须要返回的内容不同,也有很对多应不同的类别。

为了实现让计算机更好的辨认咱们须要的解决操作,须要进过编译的过程,将咱们书写的语言翻译成机器能够辨认的语言。

而整个编译阶段的流程,依照过程划分是依照下图进行的:

其中比拟要害的两个环节是词法剖析、语法分析的过程,在这两局部会将咱们的输出逐步拆分,转化为程序可能辨认的内容。

输出内容后,编译器先对内容进行词法剖析,在这一步编译器的工作是辨认源程序中的单词是否有误,编译程序中实现这种性能的局部个别称为词法分析器。通常词法剖析的输入是一个个独自的单词符号。

以 JS 为例,在这个过程中有三个次要局部:剖析函数参数、剖析变量申明、剖析函数申明。语法分析阶段的目标是辨认出源程序的语法结构(即语句或句子)是否谬误,这一阶段通常能够发现语法的谬误。在这个阶段中,编译器理论解决的是来自词法剖析得出的单词符号。

而在计算公式引擎中咱们解决数据的形式和编译原理中解决语言这一过程极度类似,从理论利用登程实现一个相似 Excel 的计算公式的计算公式引擎,咱们能够采纳的思路是从词法剖析登程,将残缺的长串公式语句拆分成小块内容,而后再进行语法分析,最初对生成语法结构树进行运算。接下来让咱们一起看看细节如何实现。

公式引擎的实现细节

咱们从公式计算开始为大家阐明,公式计算即由一个公式字符串进行计算后,得出表达式后果。比方:公式“=1+10*11”
计算后失去后果 111。电子计算机并不是人类,这样一个简略的表达式想要完全正确计算,最终变成咱们须要的数据内容,并不是简略的咱们看一眼后,口算就失去答案。实现这样类 Excel 表格计算的性能,须要通过词法剖析,语法分析,语法结构树计算这几个过程。

1. 词法剖析

中罕用的公式进行阐明。

首先咱们进行词法剖析,在这个过程中咱们将公式字符拆成字符串数组,在 Excel 表格公式计算中,表达式的公式字符串中只包含:运算符、符号、字符串、数字、数组、援用、名称这几类。

名称:sum

运算符:():/ % +

援用:A1 A11 B1

数字:100

2. 语法分析

词法剖析实现之后,咱们对词法剖析的后果进行进一步语法分析。通常计算中语法分析能够采纳表达式树或者堆栈(即逆波兰式)来解决。

这里咱们先介绍表达式树的办法。

语法分析——表达式树

应用表达式树进行剖析的过程,从一棵二叉树开始。首先咱们将词法剖析的后果依照优先级组成表达式树,表达式树的叶子结点就是操作数,外部节点是操作符。

在这个事例中,冒号的优先级最高,其次是括号,最初是除号。当这棵树造成之后,就离咱们拿到最终的运算后果很靠近了。

咱们会采纳递归调用的形式对这颗树进行运算,从根结点登程,到 sum, 始终向下递归,到 A1:A11 时,有了第一个后果,而后逐层返回计算结果。

这就完证的展现了如何实现一个公式计算。

语法分析——逆波兰算法

逆波兰算法是在语法分析阶段造成了一个堆栈(即逆波兰表达式),这个表达式的外围在于将一般咱们是用的中断表达式转换为后缀表达式。括号在运算的过程中只进行运算程序的提醒,但并不是理论参加计算的元素内容,所以在中断转后缀的过程中就能够省略掉括号内容,

而后由计算机编写代码实现运算。

这里展现了一棵树转化成对应的逆波兰式的样子。

二叉树递归 VS 逆波兰算法

与一棵树递归计算相比,逆波兰式更合乎数学计算的习惯。但理论在我的项目中解决这种公式计算的时候,到底哪一种更加能解决更简单的状况呢?

让咱们来看一个多层嵌套的公示内容:

这个公示的应用场景是 SUMIFS 函数多列求和,等价于上面这个内容:

=SUMIFS($C:$C,$B:$B,$A1)+SUMIFS($D:$D,$B:$B,$A1)+….

很显著下面的公式更加简略,采纳二叉树递归的形式,只须要判断 SUMIFS 节点的父节点以及孩子结点内容,只须要短短一行代码就能够搞定这个多列求和。

然而如果是用逆波兰算法,代码一开始遇到 SUM 就开始计算,很难断定 SUM 此时要运行的内容其实在最内层括号之中。能够解决,但却并不是最简略的。

比照后果

与堆栈的形式相比,树的解法更容易扩大、加强,能够更加轻松应答简单的公式。这在解决大量公式、简单计算就是得天独厚的劣势。

总结

在介绍完如何解析并进行公式计算的全过程之后,接下来咱们会持续介绍在公式计算引擎中计算链和异步函数的相干内容。在解决简单公式时,有向图如何求解,calcOnDemand 解法又是什么,还有在前后端计算中异步函数的花式用法。

感觉不错点个赞再走吧 \~ 后续还会为大家带来更多乏味的内容 \~

扩大浏览

  • SpreadJS 纯前端表格控件
  • SpreadJS 的内置计算公式
退出移动版