UNPKG

mm_maths

Version:

这是一个可以将数学公式推导变形,并转成js和计算的模块。

411 lines (367 loc) 9 kB
/** * @fileOverview 数学公式变形、转换成js 并计算模块 * @author <a href="http://qww.elins.cn">邱文武</a> * @version 1.0 */ require('mm_expand'); /** * 数学公式计算函数 * @property {Object} identities 恒等式(注释列表) * @property {Object} math 计算函数(注释列表) * @property {Object} convert 变换函数(注释列表) * @property {Object} symbol 符号替换函数(注释列表) */ class Maths { /** * @param {String} dir 路径 */ constructor(dir) { /** * 检索文件路径 */ this.dir = dir ? dir : __dirname; /** * 常量(集合) */ this.const = {}; /** * 变量(集合)用于替换代码中的文字,赋予值。等同于读取缓存值 */ this.vars = { // "ma5": "MA(CLOSE, 5)" }; /** * 变量值(集合)用于替换代码中的文字,赋予值。等同于读取缓存值 */ this.vals = { // "ma5": [] }; /** * 声明(集合) */ this.define = {}; this.def = this.define; /** * 已知条件 */ this.known_conditions = {}; this.known = this.known_conditions; /** * 恒等式替换函数(集合) */ this.identities = {}; this.eq = this.identities; /** * 计算函数(集合) */ this.math = {}; /** * 变换函数(集合) */ this.convert = {}; this.ct = this.convert; /** * 符号替换函数(集合) */ this.symbol = {}; this.sl = this.symbol; /** * 学科方向,mathematical数学、physical物理、chemistry化学 */ this.subject = "mathematical"; /** * 类型,base基础数学、geometry几何数学、stock股票 */ this.type = "base"; } } /** * 初始化 */ Maths.prototype.init = function() {}; /** * 载入公式 * @param {String} path 检索的路径 * @param {String} type 类型 * @param {String} expand 拓展类型, 例如: identities恒等式、convert变换函数、symbol符号、math计算函数 * @return {String} 成功返回true,失败返回错误类型; */ Maths.prototype.load_sub = function(path, type, expand) { if (!path) { path = __dirname } if (!type) { type = "math"; } if (!expand) { expand = "base"; } var dict = this[expand]; if (!dict) { console.log("不存在的类型", expand); return; } var searchFile = `*${expand}.json`; var files = $.file.getAll(path, searchFile); files.map(o => { var cg = o.loadJson(); if (cg && cg.name) { if (!cg.type || cg.type.has(type)) { if (cg.func_file && cg.key) { dict[cg.key] = cg; var f = cg.func_file.fullname(o.dirname()); if (f.hasFile()) { var func = require(f); if (func) { this[cg.key] = func; } } } } } }); }; /** * 更新 * @param {String} path 路径 * @param {String} type 类型 */ Maths.prototype.clear = function(path, type) { }; /** * 更新 * @param {String} path 路径 * @param {String} type 类型 */ Maths.prototype.update = function(path, type) { this.clear(type); this.load(path, type); this.sort(); }; /** * 载入恒等式变形函数 * @param {String} path 检索的路径 * @param {String} type 类型, 例如:default 默认,base 基础数学 * @return {String} 成功返回true,失败返回错误类型; */ Maths.prototype.load_identities = function(path, type) { this.load_sub(path, type, "identities"); }; /** * 载入转换函数 * @param {String} path 检索的路径 * @param {String} type 类型, 例如:default 默认,base 基础数学 * @return {String} 成功返回true,失败返回错误类型; */ Maths.prototype.load_convert = function(path, type) { this.load_sub(path, type, "convert"); }; /** * 载入符号处理函数 * @param {String} path 检索的路径 * @param {String} type 类型, 例如:default 默认,base 基础数学 * @return {String} 成功返回true,失败返回错误类型; */ Maths.prototype.load_symbol = function(path, type) { this.load_sub(path, type, "symbol"); }; /** * 载入计算函数 * @param {String} path 检索的路径 * @param {String} type 类型, 例如:default 默认,base 基础数学 * @return {String} 成功返回true,失败返回错误类型; */ Maths.prototype.load_math = function(path, type) { this.load_sub(path, type, "math"); }; /** * 载入相关函数 * @param {String} path 检索的路径 * @param {String} type 类型, 例如:default 默认,base 基础数学 * @return {String} 成功返回true,失败返回错误类型; */ Maths.prototype.load = function(path, type) { this.load_identities(path, type); this.load_convert(path, type); this.load_symbol(path, type); this.load_math(path, type); }; /** * 函数字典排序 */ Maths.prototype.sort = function() { this.convert = this.sort_sub(this.convert); this.symbol = this.sort_sub(this.symbol); this.identities = this.sort_sub(this.identities); }; /** * 函数排序 * @param {Object} dict 要排序的字典 */ Maths.prototype.sort_sub = function(dict) { var list = []; for(var k in dict){ list.push(dict[k]); } list.sortBy('asc', 'sort'); var dt = {}; list.map(o => dt[o.key] = o); return dt; }; /** * 设置常量 * @param {Object} constant 常量集合,采用键值对的方式 例如:{ a: 10, b: 15, d: [1,-1] } */ Maths.prototype.set_const = function(constant) { $.push(this.const, constant, true); }; /** * 重置变量 */ Maths.prototype.reset_val = function(){ for(var k in this.vars){ this.vals[k] = this.first_run_code("return " + this.vars[k]); } } /** * 设置变量 * @param {Object} vars 变量集合,采用键值对的方式 例如:{ a: null, b: 15, d: [1,-1] } */ Maths.prototype.set_var = function(vars) { $.push(this.vars, vars, true); this.reset_val(); }; /** * 下定义 * @param {Object} def 定义集合, 例如: */ Maths.prototype.set_def = function(def) { $.push(this.def, def, true); }; /** * 设置已知条件 * @param {Object} know 已知条件 { c: "a + b", e: "ab" } */ Maths.prototype.set_know = function(know) { $.push(this.know, know, true); }; /** * 设置函数头 */ Maths.prototype.head = function() { if(!this.head_value){ var head = ""; for (var k in this.math) { if (!this.const[k]) { head += "var " + k + " = math." + k + ";\r\n" } } for (var k in this.const) { var value = this.const[k]; head += "var " + k + " = constant." + k + ";\r\n" } this.head_value = head; } return this.head_value; } /** * 转换公式 * @param {String} express 表达式 * @return {String} 返回推导结果 */ Maths.prototype.convertTo = function(express){ var express = this.convert_equal(express); // 先进行符号转换 var dt = this.symbol; for(var k in dt){ var func = this[k]; if(func) { express = func(express); } } // 再进行式子转换 dt = this.convert; for(var k in dt){ var func = this[k]; if(func) { express = func(express); } } return express; }; /** * 等号转换 * @param {Object} express * @return {String} 返回公式 */ Maths.prototype.convert_equal = function(express){ var left = express.left('=', true); var right = express.right('='); if(right){ if(/\+|\-|\*|\//.test(right)) { return left + " - (" + right.trim() + ") = 0"; } else { return left + " - " + right.trim() + " = 0"; } } else { return left; } }; /** * 公式推导 * @param {String} express 表达式 * @return {String} 返回推导结果 */ Maths.prototype.derivation = function(express) { // 符号转换 }; /** * 更新标签 * @param {String} express 表达式 */ Maths.prototype.update_tag = function(express) { for(var k in this.vars){ express = express.replaceAll(this.vars[k], "vals." + k); } return express; } /** * 运行代码 * @param {String} express 表达式 * @return {Object} 执行结果 */ Maths.prototype.first_run_code = function(express) { var head = this.head(); var exp = head + express; let func = new Function('constant', 'math', exp); var ret; try { ret = func(this.const, this); } catch (e) { console.log(e); } return ret; }; /** * 运行代码 * @param {String} express 表达式 * @return {Object} 执行结果 */ Maths.prototype.run_code = function(express) { var head = this.head(); var exp = head + this.update_tag(express); let func = new Function('constant', 'math', 'vals', exp); var ret; try { ret = func(this.const, this, this.vals); } catch (e) { console.log(e); //TODO handle the exception } return ret; }; module.exports = Maths;