Calc子系统
这是Emacs非常非常强大的数值计算 数学计算 代数计算器.
对于详细的elisp接口 请查看: Elisp章节.
架构设计
calc子系统位于lisp/calc文件夹.
它的入口为lisp/calc/calc.el, 扩展功能入口为lisp/calc/calc-ext.el.
这样设计的目的是, 使用autoload机制 可以懒加载计算器功能.
入口与基础功能:
calc.el里面主要定义了各种defcustom的用户设置 以及对函数的导出.calc-ext.elcalc扩展层的导出calc-macs.elcalc的核心宏与辅助函数calc-loaddef.el自动生成的声明文件calc-menu.elCalc的菜单定义calc-mode.elCalc的显示与工作模式 比如格式 进制 对齐 等calc-keypd.el鼠标可操作的数字键盘calc-misc.el杂项功能 比如打开帮助 Info之类的calc-help.el帮助系统calc-stuff.el杂项内部工具 比如递归深度 缓存清理 随机数 矩阵等缓存
输入解析等语言功能
calc-aent.el代数表达式输入calc-incom.el复杂数据结构的增量解析 向量 复数 逗号 分号calc-lang.elcalc表达式语言设置 处理普通 扁平 大语言模式 括号逗号之类的calccomp.el把内部表达式转换为带括号、分数、上下标、向量等 格式的可显示结构calc-embed.el:Embedded Calc;把 Calc 公式嵌入普通编辑缓冲区,并负责公式识别、重算 和显示。calc-trail.el:Calc trail(历史计算轨迹)的浏览、滚动、搜索、前后跳转和窗口切换。calc-undo.el:Calc 专用 undo/redo、最后参数恢复,以及与 Calc 栈状态关联的撤销处理。calc-sel.el:在 Calc 表达式中选择子表达式、缓存选择位置、扩展或重新选择区域。calcsel2.el:基于选择区域的结构化编辑操作,例如交换、跳转、隔离、分配、合并、取负
数值运算
calc-arith.el运算的核心 定义了标量 向量 矩阵 四舍五入 比较calc-math.el基础数学函数与数值算法 平方根 对数 指数 三角 双曲calc-bin.el二进制和位运算calc-frac.el分数运算calc-cplx.el复数运算calc-comb.el组合数学calc-funcs.el特殊函数calc-fin.el金融函数
代数与符号学
calc-alg.el代数化简模块, 比如展开 因式分解 幂展开calcalg2.el导数 积分 求和 乘积 解方程 Taylor展开calcalg3.el更多代数 数值分析功能 比如插值 曲线模型calc-poly.el多项式运算calc-rewr.el按模式匹配重写表达式calc-rules.el预定义的代数重写规则集 交换律 结合分配 合并 负号 逆 因式分解 积分后处理calc-prog.elcalc内部的可编程功能calc-map.el高阶函数与集合操作 内积 外积等
线性代数
calc-vec.el向量构造 处理 打包 解包 对角矩阵 等calc-mtx.el矩阵 矩阵乘法 转置 迹 行列式 LU分解calc-stat.el向量统计函数calc-units.el物理单位calc-graph.el图形输出 与gnuplot交互calc-nlfit.el非线性曲线拟合
契约
calc子系统里
注释 [x y z] 代表类型契约.
大写代表已经归一化了
小写代表可能没归一化
精确与近似
calc子系统中 类型分为 exact与inexact
整数 分数都是exact
但是浮点数是inexact
规范化
规范化对后面的积分 化简系统有非常大的作用.
它定义了 符号的 最简状态.
规范化的函数为(math-normalize A).
整数: 已经是规范的
分数: 必须规范化
(frac NUM DEN)
必须DEN > 1 且已约分.
而且如果是整数 比如4/2 那么必须化简为整数
浮点: calc的float不是elisp的浮点 而是自己的
(float NUM EXP)
即为: \(NUM \times 10^{EXP}\).
calc要求:
NUM不能是10的倍数.NUM的绝对值必须小于: \(10^{calc-internal-prec}\),也就是这里规范了prec的精度.zero必须是'(float 0 0).
复数:
(cplx REAL IMAG)
这里的归一化条件只有: IMAG不为0 不然就是实数.
极坐标:
(polar R THETA)
必须 R > 0 且 THETA != 0 != 180
向量:
(vec A B C ...)时间:
(hms H M S)这个不多说 看calc.el即可日期 不多说
正负:
(sdev X SIGMA)这个表示 \(X \pm \sigma\)
这个要求 SIGMA > 0
数学区间:
(intv MASK LO HI)
MASK代表什么前开后闭之类的
0:
()1:
(]2:
[)3:
[]
这个不能有 LO = HI 不然区间要么是整数要么是空区间
高斯同余:
(mod N M)
要求 0 \leq N < M
语言嵌入
calc可以在其他的语言里嵌入数学表达式 然后让calc去交互式的算.
这个子系统位于 lisp/calc/calc-embd.el
函数
定义于lisp/calc/calc-funcs.el, 被lisp/calc/calc-ext.el加载 autoload.
它的函数封装接口是这样的 我以calc-erf 误差函数举例:
(defun calc-erf (arg)
(interactive "P")
(calc-slow-wrapper
(if (calc-is-inverse)
(calc-unary-op "erfc" 'calcFunc-erfc arg)
(calc-unary-op "erf" 'calcFunc-erf arg))))
它会去条件调用calcFunc-erfc或者calcFunc-erf. 也就是说
calcFunc-xxx是
calc-funcs的底层数学实现.
值得注意的是
对于递归的算法, 使用
(math-working)函数标记进度.(math-with-extra-prec)在计算内部临时提高精度