数学表达式求值
日常
对纸上常写的表达式提供安全计算器:`(1 + 2) * 3.14`、`sqrt(2)`、`sin(pi / 4)`、`log10(1000)`、`2^10`。运算符 `+ - * / % ^` 可用;函数与常量来自映射到 `Math.*` 的固定白名单 — `sin/cos/tan/asin/acos/atan/atan2`、`sinh/cosh/tanh`、`sqrt/cbrt/abs/sign/floor/ceil/round/trunc`、`log/log2/log10/ln/exp/pow`、`min/max/hypot`,外加 `pi/e/tau`。名单外的标识符被拒,因此输入无法触及页面或 JavaScript 运行时。
—
示例:
结果
8
结构上安全:标识符必须来自白名单(sin、cos、tan、sqrt、log、ln、exp、pi、e、tau、min、max、hypot、…)。无变量、无字符串字面量、无分号。
使用方法
- 输入表达式 — 运算符、括号、小数、允许的名字。
- 结果实时更新;可复制粘到别处。
- `^` 是指数(如数学,不是按位异或)。变量的幂用 `pow(x, y)` 或 `x^y`。
常见问题
- 底层使用 `eval` 吗?
- 使用 `new Function(...)`,但仅在输入按标识符解析、对白名单(`sin`、`sqrt`、`pi`、…)匹配通过之后。其它一切 — `document`、`window`、`fetch`、字符串字面量、分号 — 在执行前被拒,因此表达式无路触及 `Math.*` 之外。
- `sin` 等使用哪种角度单位?
- 弧度,与 JavaScript 的 `Math.sin` 一致。用 `pi` 表示常见角度 — `sin(pi / 2)` 为 1,`cos(pi)` 为 -1。要转换度数,传入前乘以 `pi / 180`。
- 为什么我的大计算丢精度?
- JavaScript 数字是 IEEE 754 双精度 — 约 15 位有效十进制位。`0.1 + 0.2` 给出 `0.30000000000000004`。需要更高精度(金融小数、20! 以上的阶乘等)请用专用任意精度工具或库。
- 变量或多行脚本呢?
- 故意不支持 — 保持小表面积正是安全求值的关键。需要可编程数学请用 Jupyter notebook 或桌面计算器。