Hotdry.

Article

单一二进制运算器重构全部基本数学函数:编译器数值计算的新路径与精度权衡

解析如何使用 EML 运算符 exp(x)-ln(y) 配合常数 1 重构完整科学计算器功能,探讨编译器数值计算的新路径与精度权衡。

2026-04-13compilers

在数字电路设计中,NAND 门作为唯一的基本逻辑单元能够构建出全部布尔运算,这一特性深刻影响了硬件设计的简洁性与标准化。然而,在连续数学领域,长期以来不存在类似的「单一足够运算符」—— 计算基本数学函数(如正弦、对数、指数、平方根)始终需要多种不同的运算操作。2026 年发表的一项研究打破了这一困局:作者通过系统穷举搜索发现,仅需一个二元运算符 EML (x, y) = exp (x) - ln (y) 再加上常数 1,就能构造出科学计算器的完整功能集。这一发现为编译器后端的数值计算实现、硬件映射以及符号回归开辟了全新的思考路径。

从多元到统一:基本数学函数的归约历程

现代编程语言和数学库通常提供数十种基本函数:三角函数、反三角函数、双曲函数、指数、对数、幂运算、平方根等。这些函数在教学中各自独立,在库实现中也各自拥有专门的算法路径。以 IEEE 754 浮点数标准为例,sin 函数的实现通常需要使用切比雪夫多项式逼近或 CORDIC 算法,而 log 函数则采用多项式展开配合归约技术。每种函数都需要独立的代码路径、不同的逼近多项式以及特定的误差分析方法。

该研究的核心理念是追问:这些看似多样的函数能否进一步归约?类似于布尔逻辑中所有门电路都可以用 NAND 门构建,研究者开始探索是否存在一个「连续 Sheffer 运算符」—— 即一个二元函数,配合尽可能少的终端符号,就能够表达所有基本数学函数。这一问题的难度在于:穷举所有可能的候选运算符在计算上不可行,因此研究者采用了迭代消融方法,逐步移除已知的基本操作,检验剩余集合是否仍能完备地生成所有目标函数。

研究从包含 36 个原始符号的集合出发,包括常数(π、e、i 等)、一元函数(sin、cos、exp、ln 等)以及二元运算(加、减、乘、除、幂运算、对数等)。通过系统性测试,研究者逐步将集合从 36 个元素压缩至 6 个、3 个,最终发现了令人惊讶的结论:仅需两个元素 —— 常数 1 和二元运算符 EML (x, y) = exp (x) - ln (y)—— 就足以生成全部 36 种基本操作。这一结果在数学上并非显而易见,因为 EML 本身也是由指数和对数复合而成,但它确实满足「Sheffer 运算符」的定义:单独使用它即可生成完整的科学计算器功能。

EML 运算符的构造与表达

具体而言,EML 运算符的定义为 eml (x, y) = exp (x) - ln (y)。利用这个运算符,基本数学函数的表达变得高度结构化。例如,指数函数可以直接计算为 e^x = eml (x, 1),因为 exp (x) - ln (1) = exp (x) - 0 = exp (x)。对数函数的表达式则更为复杂,需要三层嵌套:ln (z) = eml (1, eml (eml (1, z), 1))。这种嵌套结构反映了 EML 表达式的深度特性 —— 不同的基本函数需要不同深度的表达式树。

从编译器实现的角度看,这种统一表示具有独特的语法特性。所有 EML 表达式都可以视为一棵二叉树,其语法规则简化为 S → 1 | eml (S, S)。这种形式化描述与数字电路中的标准单元库极为相似:如同所有数字电路最终都可以还原为 NAND 门的组合,所有基本数学函数最终都可以还原为 EML 运算符的树状组合。研究者提供了完整的「自举」发现链,展示了从 EML 和常数 1 如何逐步构建出加法、乘法、三角函数、双曲函数乃至数学常数 π 和 e。

值得注意的是,EML 表达式的求值必须在复数域内进行,至少在内部计算层面如此。产生诸如 π 和 i 等常数需要计算 ln (-1),这涉及复数对数的主支定义。这一特性与量子计算有微妙相似:量子计算使用复数振幅来计算实数概率,EML 则使用复数中间结果来计算实数基本函数。研究者指出,这种内部复数依赖在实际使用中仅造成轻微不便,在主流数学软件(如 Mathematica)和数值计算库(如 NumPy、PyTorch)中均能正常工作。

编译器视角下的精度权衡与实现考量

将 EML 统一表示应用于实际编译器设计需要权衡多个工程因素。首先是表达式深度问题:虽然 EML 在理论上具有完备性,但具体函数的 EML 表示可能具有相当大的深度。例如,自然对数的 RPN 代码长度为 7,而乘法的深度达到 8,更复杂的三角函数可能需要更深更长的表达式。这种深度增加直接影响了求值效率 —— 更多的 exp 和 ln 操作意味着更多的浮点运算和更大的累计误差。

精度方面,传统数学库针对每种函数精心选择逼近多项式的次数和系数,以在指定精度(如 IEEE 754 单精度或双精度)下达到最小误差。而 EML 方法将所有函数统一映射到 exp 和 ln 的组合,误差来源变得更加复杂。每一次 exp 或 ln 的调用都会引入舍入误差,这些误差在深层嵌套表达式中可能传播和累积。研究者通过数值实验表明,在双精度浮点下,EML 表达式能够达到接近机器精度的结果,但需要对特殊值(如零和无穷大)进行谨慎处理。

复数主支的选择是另一个关键问题。EML 内部计算依赖复数对数,而复数对数在负实轴上存在分支切割,导致 ln (-1) = iπ 的定义可能因分支选择不同而相差 2πi。研究者发现,直接使用标准主支会导致某些常数(如虚数单位 i)的符号错误,需要在编译器层面进行手动修正或重新定义 EML 本身的分支行为。这提示任何基于 EML 的编译器实现都必须仔细处理复数域的数学语义。

从优化空间角度看,EML 统一表示为编译器优化提供了新的可能性。由于所有函数都表达为相同基本操作的组合,编译器可以进行跨函数的公共子表达式消除、指令调度优化,甚至在特定目标硬件(如 FPGA 或专用数学协处理器)上实现 EML 运算符的硬连线支持。研究者提到,EML 代码可以在一类单指令堆栈机上执行,类似于逆波兰记号(RPN)计算器,这为专用硬件实现提供了理论基础。

应用前景与开放问题

EML 运算符的发现不仅具有理论意义,还带来了实际的工程应用潜力。在符号回归领域,研究者展示了如何使用梯度下降方法从数值数据中恢复闭式基本函数。具体做法是将 EML 树结构参数化,通过优化权重来拟合训练数据,当权重最终「硬化」为 0 或 1 时,得到的表达式恰好是某个基本函数。这种方法的成功依赖于 EML 树结构本身的良好特性:深度为 2 时可实现 100% 恢复,深度为 3-4 时约 25% 恢复。研究者开发的 SymbolicRegression 包提供了完整的工具链,包括 Rust 实现的高效验证程序和 Python 端到端训练流程。

对于编译器社区而言,EML 方法提出了若干值得深入探索的方向。其一是设计专用的 EML 编译器 pass,将标准数学函数自动转换为 EML 形式,并在后端应用针对 exp 和 ln 的优化策略;其二是探索 EML 在模拟计算或专用集成电路(ASIC)中的硬件实现可能性,利用其统一的二叉树结构进行电路布局优化;其三是研究 EML 表示与其他函数表示(如切比雪夫逼近、CORDIC)在精度 - 性能谱上的权衡关系,为不同应用场景提供自适应选择。

该研究同时留下若干开放问题:是否存在不使用特殊常数(如 1、e 或 -∞)的 EML 型运算符?是否存在单一的一元运算符同时具备 Sheffer 属性和神经网络激活函数的良好特性?这些问题的探索将进一步深化我们对基本数学函数结构的理解,并为未来编译器和计算架构的设计提供新的思路。

资料来源:本文主要参考 arXiv 预印本 "All elementary functions from a single binary operator"(arXiv:2603.21852),作者为克拉科夫雅盖隆大学的 Andrzej Odrzywołek。

compilers