数学表达式
- Switch to English Document
介绍
本框架是一种针对数学公式解析的有效工具,能够解析包含嵌套函数,包含函数,数列步长累加等数学公式,返回值是一个数值的结果对象,同时也可以进行比较运算的操作,再进行比较的时候,返回值是一个布尔值结果对象。
PS 请尽量使用 1.3.1 版本以及以上的版本,这将有助于您使用更加稳定的版本,修复了 1.2.x
中所有已知的bug
-
Maven依赖坐标
您可以直接使用maven将本框架导入到项目中使用,能够高效的使用该功能
<dependencies><dependency><groupId>io.github.BeardedManZhao</groupId><artifactId>mathematical-expression</artifactId><version>1.3.4</version></dependency>
</dependencies>
您也可以直接通过gradle将“mathematical-expression”载入到您的框架中,使用下面的依赖即可。
dependencies {implementation 'io.github.BeardedManZhao:mathematical-expression:1.3.4'
}
为什么要选择 mathematical-expression
mathematical-expression 具有简单,快速,易上手,支持的语言种类多 等优势,它具有 C Java python 版本的 API 使用方法几乎一致。
易于使用的API
调用库是很简单的,您可以使用如下代码进行计算,当然,如果您不需要进行检查,您还可以将下面的计算代码压缩为 System.out.println(Mathematical_Expression.getInstance(Mathematical_Expression.bracketsCalculation2).calculation("(1+2)*3"));
能够有效的减少代码量!
import core.Mathematical_Expression;
import core.calculation.Calculation;
import exceptional.WrongFormat;public class MAIN {public static void main(String[] args) throws WrongFormat {final Calculation instance = Mathematical_Expression.getInstance(// 在这里选择您要使用的不同计算组件即可Mathematical_Expression.bracketsCalculation2);// 如果您确保表达式的无误,可以不检查instance.check("(1+2)*3");System.out.println(instance.calculation("(1+2)*3"));}
}
种类繁多的计算组件
在mathematical-expression 中,我们提供了多种计算组件,您可以根据需要选择不同的计算组件,以实现不同的功能,同时还保持着相同的API调用方式。
package utils;import core.Mathematical_Expression;
import core.calculation.Calculation;
import core.calculation.function.Functions;
import exceptional.WrongFormat;// 准备一个数学函数 x 的阶乘 + 1
@Functions("f(x) = x! + 1")
public class MAIN {public static void main(String[] args) throws WrongFormat {// 将 MAIN 注解的函数注册 并进行使用Mathematical_Expression.register_function(MAIN.class);final Calculation instance = Mathematical_Expression.getInstance(// 在这里选择函数计算组件即可Mathematical_Expression.functionFormulaCalculation2);// 如果您确保表达式的无误,可以不检查instance.check("f(1 + 2) - 3");System.out.println(instance.calculation("f(1 + 2) - 3"));/*----------------------------------*/// 您还可以用快速计算组件计算区间 [1+2, 30] 之间的求和final Calculation instance1 = Mathematical_Expression.getInstance(// 在这里选择快速求和计算组件即可 API 和上面是一样的Mathematical_Expression.fastSumOfIntervalsBrackets);instance1.check("1 + 2, 30");System.out.println(instance1.calculation("1 + 2, 30"));}
}
超高的灵活度
在其中的任何步骤所需要的函数,计算好的任何对象,都可以被单独获取到进行您想要的操作。例如数学函数是一种复杂的对象,其编译成功之后,您可以直接获取到它的函数对象,并不仅仅局限于在
mathematical-expression 中使用!
import core.Mathematical_Expression;
import core.calculation.function.Functions;
import core.calculation.function.ManyToOneNumberFunction;
import exceptional.WrongFormat;// 准备一个数学函数 x 的阶乘 + 1
@Functions("f(x) = x! + 1")
public class MAIN {public static void main(String[] args) throws WrongFormat {// 将 MAIN 注解的函数注册 并进行使用Mathematical_Expression.register_function(MAIN.class);// 提取出 f(x) = x! + 1 的函数对象 我们知道这个函数的名字就是 ffinal ManyToOneNumberFunction f = Mathematical_Expression.getFunction("f");// 单独使用 f 进行计算final double run = f.run(3);System.out.println(run);}
}
框架架构
通过 mathematical-expression 库直接获取到计算组件并进行计算
package utils;import core.Mathematical_Expression;
import core.calculation.number.NumberCalculation;
import core.container.CalculationNumberResults;
import exceptional.WrongFormat;public class MAIN {public static void main(String[] args) throws WrongFormat {// 构建需要计算的两种表达式String s1 = "1 + 20 - 2 + 4", s2 = "1 + 20 - (2 + 4)";// 通过库获取到计算无括号表达式的计算组件NumberCalculation prefixExpressionOperation = Mathematical_Expression.getInstance(Mathematical_Expression.prefixExpressionOperation, "prefixExpressionOperation");// 通过库获取到计算有括号表达式的计算组件NumberCalculation bracketsCalculation2 = Mathematical_Expression.getInstance(Mathematical_Expression.bracketsCalculation2, "bracketsCalculation2");// 将第一个公式传递给无括号表达式的计算组件prefixExpressionOperation.check(s1);CalculationNumberResults calculation1 = prefixExpressionOperation.calculation(s1);// 打印出第一个表达式的计算结果System.out.println("计算层数:" + calculation1.getResultLayers() + "\n计算结果:" + calculation1.getResult() +"\n计算来源:" + calculation1.getCalculationSourceName());// 将第二个公式传递给无括号表达式的计算组件bracketsCalculation2.check(s2);CalculationNumberResults calculation2 = bracketsCalculation2.calculation(s2);// 打印出第二个表达式的计算结果System.out.println("计算层数:" + calculation2.getResultLayers() + "\n计算结果:" + calculation2.getResult() +"\n计算来源:" + calculation2.getCalculationSourceName());}
}
-
运行结果
通过导入包可以获取到各个计算组件的模块对象,能够有效的减少代码导包代码。
计算层数:1
计算结果:23.0
计算来源:prefixExpressionOperation
计算层数:2
计算结果:15.0
计算来源:bracketsCalculation2
计算管理者
-
类组件:core.manager.CalculationManagement
-
介绍:
管理者是一个为了同时使用单例与动态对象而设计的一个组件,管理者的存在可以使得每一个组件能够被名字所获取到,相同名字的组件,在内存中的存储地址也是一样的,避免了冗余组件的调用,同时针对需要使用到动态成员的组件,也可以通过一个新名字获取到一个新组件。
-
API使用示例
package utils;import core.calculation.number.FunctionFormulaCalculation;
import core.calculation.number.PrefixExpressionOperation;
import core.manager.CalculationManagement;
import exceptional.WrongFormat;public class MAIN {public static void main(String[] args) {// 实例化三个计算组件// TODO getInstance会自动从管理者中获取,如果没有获取到,就会创建并注册然后再返回数据 这个方法即可以创建也可以访问管理者PrefixExpressionOperation a = PrefixExpressionOperation.getInstance("a");FunctionFormulaCalculation b = FunctionFormulaCalculation.getInstance("b");PrefixExpressionOperation a1 = PrefixExpressionOperation.getInstance("a1");// 注册一个名为“a”的无括号解析组件CalculationManagement.register(a);// 注册一个名为“b”的函数解析组件CalculationManagement.register(b);// 注册一个名为“a1”的无括号解析组件CalculationManagement.register(a1);// 打印我们示例化的 与 从管理者获取到的组件的内存数据是否一致System.err.println(a + " " + CalculationManagement.getCalculationByName("a"));System.err.println(b + " " + CalculationManagement.getCalculationByName("b"));System.err.println(a1 + " " + CalculationManagement.getCalculationByName("a1"));}
}
-
运行结果
最后三行就是内存数据的比较,实例化出来的组件与管理者中的组件在内存中是一样的,但是不同名称的组件是不同的。
[INFO][Calculation Management][22-11-14:11]] : +============================== Welcome to [mathematical expression] ==============================+
[INFO][Calculation Management][22-11-14:11]] : + Start time Mon Nov 14 11:45:13 CST 2022
[INFO][Calculation Management][22-11-14:11]] : + Calculation component manager initialized successfully
[INFO][Calculation Management][22-11-14:11]] : + For more information, see: https://github.com/BeardedManZhao/mathematical-expression.git
[INFO][Calculation Management][22-11-14:11]] : +--------------------------------------------------------------------------------------------------+
[INFO][Calculation Management][22-11-14:11]] : A computing component is registered a
[INFO][Calculation Management][22-11-14:11]] : A computing component is registered PrefixExpressionOperation
[INFO][Calculation Management][22-11-14:11]] : A computing component is registered BracketsCalculation2
[INFO][Calculation Management][22-11-14:11]] : A computing component is registered b
[INFO][Calculation Management][22-11-14:11]] : A computing component is registered a1
[INFO][Calculation Management][22-11-14:11]] : A computing component is registered a
[INFO][Calculation Management][22-11-14:11]] : A computing component is registered b
[INFO][Calculation Management][22-11-14:11]] : A computing component is registered a1
[INFO][Calculation Management][22-11-14:11]] : Get the [a] component from the manager
[INFO][Calculation Management][22-11-14:11]] : Get the [b] component from the manager
[INFO][Calculation Management][22-11-14:11]] : Get the [a1] component from the manager
core.calculation.number.PrefixExpressionOperation@8ad73b core.calculation.number.PrefixExpressionOperation@8ad73b
core.calculation.number.FunctionFormulaCalculation@762604 core.calculation.number.FunctionFormulaCalculation@762604
core.calculation.number.PrefixExpressionOperation@41e737 core.calculation.number.PrefixExpressionOperation@41e737
计算组件介绍
无括号表达式
-
类组件:core.calculation.number.PrefixExpressionOperation
-
介绍
针对一个没有括号,但是有加减乘除以及取余等运算操作的数学表达式而设计的组件,该组件可以实现带有优先级计算的功能,其中通过前缀表达式解析计算,将操作数与操作符一同存储到栈,在存储的同时配有计算优先级比较,如果当下的优先级较小,就先将上一个操作数与操作符与当前操作数进行运算,形成一个新的数值,然后再入栈。
-
API使用示例
该组件支持的运算符有: a+b a-b a*b a/b a%b
import core.calculation.number.PrefixExpressionOperation;
import core.container.CalculationNumberResults;
import exceptional.WrongFormat;public class MAIN {public static void main(String[] args) throws WrongFormat {// 获取一个计算无括号表达式的函数PrefixExpressionOperation prefixExpressionOperation = PrefixExpressionOperation.getInstance("p");// 创建一个表达式String s = "1 + 2 + 4 * 10 - 3";// 检查表达式是否有错误prefixExpressionOperation.check(s);// 开始计算结果CalculationNumberResults calculation = prefixExpressionOperation.calculation(s);// 打印结果数值System.out.println("计算层数:" + calculation.getResultLayers() + "\n计算结果:" + calculation.getResult() +"\n计算来源:" + calculation.getCalculationSourceName());}
}
-
运行结果
在API调用中,对函数的运行结果进行了打印,可以看到,组件计算的返回值是一个结果集对象,在该对象中存储的就是很多有关计算结果相关的信息。
计算层数:2
计算结果:40.0
计算来源:p
嵌套括号表达式
-
类组件:core.calculation.number.BracketsCalculation2
-
介绍:
嵌套括号表达式解析组件,能够针对带有多个括号的数学表达式进行解析与结果计算,针对嵌套括号进行优先级的解析与计算,该组件依赖于“core.calculation.number.PrefixExpressionOperation”,在该组件中采用递归进行括号的解析,然后将最内层面的表达式提供给“core.calculation.number.PrefixExpressionOperation”进行计算。
-
API使用示例
该组件支持的运算符有: a+b a-b a*b a/b a%b ( )
package utils;import core.calculation.number.BracketsCalculation2;
import core.container.CalculationNumberResults;
import exceptional.WrongFormat;public class MAIN {public static void main(String[] args) throws WrongFormat {// 获取一个计算无括号表达式的函数BracketsCalculation2 bracketsCalculation = BracketsCalculation2.getInstance("BracketsCalculation");// 创建一个表达式String s = "1 + 2 + 4 * (10 - 3)";// 检查表达式是否有错误bracketsCalculation.check(s);// 开始计算结果CalculationNumberResults calculation = bracketsCalculation.calculation(s);// 打印结果数值System.out.println("计算层数:" + calculation.getResultLayers() + "\n计算结果:" + calculation.getResult() +"\n计算来源:" + calculation.getCalculationSourceName());}
}
-
运行结果
在API调用中,对表达式的计算结果进行了打印,可以看到,组件计算的返回值是一个数值结果对象,在该对象中存储的就是很多有关计算结果相关的信息。
计算层数:2
计算结果:31.0
计算来源:BracketsCalculation
数学比较表达式
-
类组件:core.calculation.bool.BooleanCalculation2
-
介绍
使用比较运算符两个括号表达式是否相互成立的一个组件,返回值是一个布尔类型的结果对象,该组件能够比较两个数值的大小等,也可以比较两个表达式之间的大小等关系,依赖于组件“core.calculation.bool.BooleanCalculation2”
-
API使用示例
该组件支持的运算符如API中演示
package utils;import core.calculation.bool.BooleanCalculation2;
import core.container.CalculationBooleanResults;
import exceptional.WrongFormat;public class MAIN {public static void main(String[] args) throws WrongFormat {// 获取一个计算数学比较表达式的组件BooleanCalculation2 booleanCalculation2 = BooleanCalculation2.getInstance("Bool");// 创建3个表达式String s1 = "1 + 2 + 4 * (10 - 3)";String s2 = "2 + 30 + (2 * 3) - 1";String s3 = "1 + 3 * 10";extracted(booleanCalculation2, s1 + " > " + s2);// false extracted(booleanCalculation2, s1 + " < " + s2);// true extracted(booleanCalculation2, s1 + " = " + s3);// true extracted(booleanCalculation2, s1 + " == " + s3);// true extracted(booleanCalculation2, s1 + " != " + s3);// false extracted(booleanCalculation2, s1 + " <> " + s3);// false extracted(booleanCalculation2, s1 + " <= " + s3);// true extracted(booleanCalculation2, s1 + " >= " + s3);// true extracted(booleanCalculation2, s1 + " != " + s2);// true extracted(booleanCalculation2, s1 + " <> " + s2);// true }private static void extracted(BooleanCalculation2 booleanCalculation2, String s) throws WrongFormat {// 检查表达式是否有错误booleanCalculation2.check(s);// 开始计算结果CalculationBooleanResults calculation = booleanCalculation2.calculation(s);// 打印结果数值System.out.println("计算层数:" + calculation.getResultLayers() + "\t计算结果:" + calculation.getResult() +"\t计算来源:" + calculation.getCalculationSourceName());}
}
- 运行结果
计算层数:4 计算结果:false 计算来源:Bool
计算层数:4 计算结果:true 计算来源:Bool
计算层数:3 计算结果:true 计算来源:Bool
计算层数:3 计算结果:true 计算来源:Bool
计算层数:3 计算结果:false 计算来源:Bool
计算层数:3 计算结果:false 计算来源:Bool
计算层数:3 计算结果:true 计算来源:Bool
计算层数:3 计算结果:true 计算来源:Bool
计算层数:4 计算结果:true 计算来源:Bool
计算层数:4 计算结果:true 计算来源:Bool
区间累加表达式
-
类组件:core.calculation.number.CumulativeCalculation
-
介绍
在数学表达式中,往往有这样的一种公式,公式内容如下图所示,可以看到需要进行累加的数列操作,那么在这种公式的需求下,您可以通过上面的类组件去达到您所需要的目的。
-
API使用示例
语法层面于其他组件几乎一致,数学表达式的撰写于组件的计算示例就如下面所示,在这里展示的就是一个累加数学公式的计算。
package utils;import core.calculation.number.CumulativeCalculation;
import core.container.CalculationNumberResults;
import exceptional.WrongFormat;public class MAIN {public static void main(String[] args) throws WrongFormat {// 获取一个计算累加数学表达式的组件CumulativeCalculation cumulativeCalculation = CumulativeCalculation.getInstance("zhao");// 构建一个数学表达式,这里的"n[1,10,1]"就类似数学中的累加符号,n会在这个区间内不断增加,每增加一次都会被带入公式中计算一次// 其中[1,10,1]中的最后一个1 代表增加步长,能够实现区间内不同等差值的累加String s = "n[1,10,1] 2 * (n + 1)";// 检查数学表达式cumulativeCalculation.check(s);// 计算结果CalculationNumberResults calculation = cumulativeCalculation.calculation(s);System.out.println("计算层数:" + calculation.getResultLayers() + "\t计算结果:" + calculation.getResult() +"\t计算来源:" + calculation.getCalculationSourceName());}
}
- 运行结果
计算层数:21 计算结果:130.0 计算来源:zhao
函数运算表达式
-
类组件:core.calculation.number.FunctionFormulaCalculation
-
介绍
针对一些函数的操作,在该框架中也有支持,可以使用上面的类进行这中需要函数的数学表达式的书写,需要注意的是,一切在表达式中使用到的函数都需要在“CalculationManagement”中进行逻辑注册,使得计算的时候可以访问到函数
-
API使用示例
package utils;import core.calculation.function.ManyToOneNumberFunction;
import core.calculation.number.FunctionFormulaCalculation;
import core.container.CalculationNumberResults;
import core.manager.CalculationManagement;
import exceptional.WrongFormat;public class MAIN {public static void main(String[] args) throws WrongFormat {// 实例化一个函数 名为DoubleValue 用于将一个数值乘2ManyToOneNumberFunction myFunction = new ManyToOneNumberFunction("DoubleValue") {/*** 函数的运行逻辑实现** @param numbers 这里是函数的数据输入对象,由框架向这里传递数据输入参数* @return 这里是数据经过函数转换之后的数据*/@Overridepublic double run(double... numbers) {// 在这里的参数中,第一个参数就是被FunctionFormulaCalculation所传入的参数return numbers[0] * 2;}};// 将函数注册到管理者中CalculationManagement.register(myFunction);// 获取一个计算累加数学表达式的组件FunctionFormulaCalculation functionFormulaCalculation = FunctionFormulaCalculation.getInstance("zhao");// 构建一个数学表达式,表达式中使用到了函数 DoubleValueString s = "2 * DoubleValue(2 + 3) + 1";// 检查数学表达式functionFormulaCalculation.check(s);// 计算结果CalculationNumberResults calculation = functionFormulaCalculation.calculation(s);System.out.println("计算层数:" + calculation.getResultLayers() + "\t计算结果:" + calculation.getResult() +"\t计算来源:" + calculation.getCalculationSourceName());}
}
- 运行结果
[INFO][zhao][22-11-14:11]] : Find and prepare the startup function: DoubleValue
计算层数:1 计算结果:21.0 计算来源:BracketsCalculation2
多参函数运算表达式
-
类组件:core.calculation.number.FunctionFormulaCalculation2
-
介绍
针对一些在表达式中使用了函数的表达式计算,可以使用上面的类进行操作,它是“core.calculation.number.FunctionFormulaCalculation”类的升级版,从1.1版本开始出现,同时也是它的一个子类拓展实现。
相较于父类,本组件弥补了父类只能解析带有一个参数函数表达式的不足,在该组件中,可以使用很多的实参进行函数的运算,例如sum(
1,2,3)
这类函数,就是一个多参函数,接下来请看API的使用示例,在此示例中,展示了多惨函数表达式的计算与结果。
package utils;import core.calculation.function.ManyToOneNumberFunction;
import core.calculation.number.FunctionFormulaCalculation2;
import core.container.CalculationNumberResults;
import core.manager.CalculationManagement;
import exceptional.WrongFormat;public class MAIN {public static void main(String[] args) throws WrongFormat {// 实现一个sum函数ManyToOneNumberFunction manyToOneNumberFunction = new ManyToOneNumberFunction("sum") {/*** 函数的运行逻辑实现** @param numbers 这里是函数的数据输入对象,由框架向这里传递数据输入参数* @return 这里是数据经过函数转换之后的数据*/@Overridepublic double run(double... numbers) {double res = 0;for (double number : numbers) {res += number;}return res;}};// 将该函数注册到管理者CalculationManagement.register(manyToOneNumberFunction);// 获取到新版本的函数计算组件FunctionFormulaCalculation2 functionFormulaCalculation2 = FunctionFormulaCalculation2.getInstance("zhao");// 构建我们需要计算的公式 TODO 在这个表达式中的函数sum形参,不只有1个,是多参的函数String s = "2 * (200 - sum(1 + 10.1, 2, 3)) + sum(10, 20)";// 启用共享池,能够加快计算的速度,计算的公式越复杂,该共享池的效果越显著functionFormulaCalculation2.setStartSharedPool(true);// 开始检查公式是否有错误functionFormulaCalculation2.check(s);// 获取到计算结果CalculationNumberResults calculation = functionFormulaCalculation2.calculation(s);System.out.println("计算层数:" + calculation.getResultLayers() + "\t计算结果:" + calculation.getResult() +"\t计算来源:" + calculation.getCalculationSourceName());}
}
- 运行结果
计算层数:2 计算结果:397.8 计算来源:BracketsCalculation2
数学函数表达式注册
您可以直接使用一个函数的数学表达式来实现某个函数的注册,函数表达式的格式为 函数名字(参数1,参数2,参数3) = 函数逻辑表达式,例如 参数1 + 参数2
下面是一个注册示例
这样注册的函数 也是可以直接在数学表达式中使用的!
package utils;import core.Mathematical_Expression;
import core.manager.ConstantRegion;
import exceptional.WrongFormat;public class MAIN {public static void main(String[] args) throws WrongFormat {System.out.println(ConstantRegion.VERSION);// 开始进行注册 TODO 我们在这里注册了一个叫做 mySum 的函数 它接收两个参数 输出的是两个参数的求和结果if (Mathematical_Expression.register_function("mySum(a, b) = a + b")) {System.out.println("函数注册成功!");}}
}
快速区间求和计算组件(基于括号表达式)
-
类组件:mathematical_expression/core/calculation/number/fastSumOfIntervalsBrackets.py
-
介绍 1.15版本的新产物,区间快速求和组件,是针对一个等差为1的区间进行所有元素求和的快速组件,它将一个区间在逻辑上模拟成为一个数学数列,并通过求和公式进行快速的求和。
该组件实现了共享池计算功能,将检查,计算,以及上一次结果记录实现,能够加快计算速度,具体API调用如下所示。
package utils;import core.calculation.number.FastSumOfIntervalsBrackets;
import core.container.CalculationNumberResults;
import exceptional.WrongFormat;public class MAIN {public static void main(String[] args) throws WrongFormat {// 获取到区间求和快计算组件FastSumOfIntervalsBrackets fast = FastSumOfIntervalsBrackets.getInstance("fast");// 构建一个需要计算的表达式 下面的表达式代表 从 11 = (1+10) 加到 13 = (20-(5+2)) 默认等差为2 结果应为 24String s = "1 + 10, 20 - (5 + 2)";// 检查表达式,共享池从1.2版本后,已经是默认启用的状态了!不需要手动设置了// fast.setStartSharedPool(true);fast.check(s);// 从1.2版本之后,累加组件支持设置步长参数,1.2.1版本中开始正式支持步长区间的求和fast.step = 2;// 开始计算CalculationNumberResults calculation = fast.calculation(s);// 打印计算结果System.out.println("计算层数:" + calculation.getResultLayers() + "\t计算结果:" + calculation.getResult() +"\t计算来源:" + calculation.getCalculationSourceName());}
}
- 运行结果 从上面代码中我们可以看到,快速区间求和计算的公式由被逗号分割的两个括号表达式组成
计算层数:3 计算结果:24.0 计算来源:fast
快速区间累乘计算组件(基于括号表达式)
-
类组件:core.calculation.number.FastMultiplyOfIntervalsBrackets
-
介绍 1.2版本的新产物,区间快速累乘组件,是针对一个等差为n的区间进行所有元素累乘的快速组件,它将一个区间在逻辑上模拟成为一个数学数列,并通过求和公式进行快速的累乘。
该组件实现了共享池计算功能,将检查,计算,以及上一次结果记录实现,能够加快计算速度,具体API调用如下所示。
package utils;import core.calculation.number.FastMultiplyOfIntervalsBrackets;
import core.container.CalculationNumberResults;
import exceptional.WrongFormat;/*** 测试用类*/
public class MAIN {public static void main(String[] args) throws WrongFormat {// 获取到区间求和快计算组件FastMultiplyOfIntervalsBrackets fast = FastMultiplyOfIntervalsBrackets.getInstance("fast");// 构建一个需要计算的表达式 下面的表达式代表 从 11 = (1+10) 乘到 13 = (20-(5+2)) 默认等差为2// 结果应为 11 * 13 = 143String s = "1 + 10, 20 - (5 + 2)";// 检查表达式,共享池从1.2版本后,已经是默认启用的状态了!不需要手动设置了// fast.setStartSharedPool(true);fast.check(s);// 从1.2版本之后,累加组件支持设置步长参数,1.2.1版本中开始正式支持步长区间的求和fast.step = 2;// 开始计算CalculationNumberResults calculation = fast.calculation(s);// 打印计算结果System.out.println("计算层数:" + calculation.getResultLayers() + "\t计算结果:" + calculation.getResult() +"\t计算来源:" + calculation.getCalculationSourceName());}
}
-
运行结果
从上面代码中我们可以看到,快速区间求和计算的公式由被逗号分割的两个括号表达式组成
计算层数:3 计算结果:143.0 计算来源:fast
高阶操作
数学方式的函数注册与计算
package top.lingyuzhao;import core.Mathematical_Expression;
import core.calculation.Calculation;
import core.calculation.function.FunctionPackage;
import exceptional.WrongFormat;public class MAIN {public static void main(String[] args) throws WrongFormat {// 将 f 函数注册进来Mathematical_Expression.register_function("f(x) = x * x");// 准备要计算的表达式final String data = "1 + f(20) + 3";// 获取到计算组件final Calculation instance = Mathematical_Expression.getInstance(Mathematical_Expression.functionFormulaCalculation2);// 检查与计算instance.check(data);System.out.println(instance.calculation(data));}
}
下面就是计算结果
CalculationNumberResults{result=404.0, source='BracketsCalculation2'}
匿名实现的函数注册与计算
package top.lingyuzhao;import core.Mathematical_Expression;
import core.calculation.Calculation;
import core.calculation.function.FunctionPackage;
import core.calculation.function.ManyToOneNumberFunction;
import exceptional.WrongFormat;public class MAIN {public static void main(String[] args) throws WrongFormat {// 将 f 函数注册进来Mathematical_Expression.register_function(new ManyToOneNumberFunction("f") {@Overridepublic double run(double... numbers) {return numbers[0] * numbers[0];}});// 准备要计算的表达式final String data = "1 + f(20) + 3";// 获取到计算组件final Calculation instance = Mathematical_Expression.getInstance(Mathematical_Expression.functionFormulaCalculation2);// 检查与计算instance.check(data);System.out.println(instance.calculation(data));}
}
下面就是计算结果
CalculationNumberResults{result=404.0, source='BracketsCalculation2'}
注解方式实现函数的注册与计算
package utils;import core.Mathematical_Expression;
import core.calculation.Calculation;
import core.calculation.function.Functions;
import exceptional.WrongFormat;@Functions({// 这里是需要被注册的两个函数 在这里标记一下"f(x) = x * x","ff(x) = f(x) + 1"
})
public class MAIN {public static void main(String[] args) throws WrongFormat {// 将 MAIN 类中标记的所有函数注册if (Mathematical_Expression.register_function(MAIN.class)) {// 构建需要计算的表达式final String string = "1 + ff(1 + 2) * 2";// 获取到函数计算组件Calculation calculation = Mathematical_Expression.getInstance(Mathematical_Expression.functionFormulaCalculation2);// 开始进行计算calculation.check(string);System.out.println(calculation.calculation(string));}}
}
下面就是计算结果
CalculationNumberResults{result=21.0, source='functionFormulaCalculation2'}
直接获取到函数对象 以及 将函数对象保存到文件
所有的函数对象都可以被提取出来,而针对“数学函数表达式”所注册的函数是可以被保存到文件中的,我们可以直接进行序列化的操作保存它,接下来我们将展示一些示例。
提取出函数对象 单独计算
package utils;import core.Mathematical_Expression;
import core.calculation.function.Functions;
import core.calculation.function.ManyToOneNumberFunction;
import exceptional.WrongFormat;import java.io.IOException;@Functions({// 这里是需要被注册的两个函数 在这里标记一下 分别是 f 和 ff 两个函数"f(x) = x * x","ff(x) = f(x) + 1"
})
public class MAIN {public static void main(String[] args) throws WrongFormat {// 将 MAIN 类中标记的所有函数注册if (Mathematical_Expression.register_function(MAIN.class)) {// 获取到 ff 函数final ManyToOneNumberFunction ff = Mathematical_Expression.getFunction("ff");// 计算出结果final double run = ff.run(1024);System.out.println(run);}}
}
下面就是计算结果
1048577.0
提取出函数对象 保存到文件
需要注意的是,如果您要保存的函数中使用到了其它函数,例如 ff(x) = f(x) + 1
,那么您需要将 f(x) = x * x
也保存到文件中,在下面展示的是保存一个函数的代码。
package utils;import core.Mathematical_Expression;
import core.calculation.function.ExpressionFunction;
import core.calculation.function.Functions;
import core.calculation.function.ManyToOneNumberFunction;
import exceptional.WrongFormat;import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;@Functions({// 这里是需要被注册的两个函数 在这里标记一下 分别是 f 和 ff 两个函数"f(x) = x * x","ff(x) = f(x) + 1"
})
public class MAIN {public static void main(String[] args) throws WrongFormat, IOException {// 将 MAIN 类中标记的所有函数注册if (Mathematical_Expression.register_function(MAIN.class)) {// 获取到 ff 函数final ManyToOneNumberFunction ff = Mathematical_Expression.getFunction("f");// 保存到文件 TODO ExpressionFunction 的函数是可以被保存到文件中的try (final ObjectOutputStream objectOutput = new ObjectOutputStream(Files.newOutputStream(Paths.get("C:\\Users\\zhao\\Desktop\\fsdownload\\f.me")))) {// 将 ff 保存到数据流中((ExpressionFunction) ff).saveTo(objectOutput);}}}
}
事实上,您还可以一次保存多个函数对象到一个文件中,这将会有助于帮助您解决函数依赖问题!
package utils;import core.Mathematical_Expression;
import core.calculation.function.ExpressionFunction;
import core.calculation.function.Functions;
import core.calculation.function.ManyToOneNumberFunction;
import exceptional.WrongFormat;import java.io.IOException;
import java.io.ObjectOutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;@Functions({// 这里是需要被注册的两个函数 在这里标记一下 分别是 f 和 ff 两个函数"f(x) = x * x","ff(x) = f(x) + 1"
})
public class MAIN {public static void main(String[] args) throws WrongFormat, IOException {// 将 MAIN 类中标记的所有函数注册if (Mathematical_Expression.register_function(MAIN.class)) {// 获取到 ff 函数 以及 f 函数final ManyToOneNumberFunction ff = Mathematical_Expression.getFunction("ff");final ManyToOneNumberFunction f = Mathematical_Expression.getFunction("f");// 保存到文件 TODO ExpressionFunction 的函数是可以被保存到文件中的try (final ObjectOutputStream objectOutput = new ObjectOutputStream(Files.newOutputStream(Paths.get("C:\\Users\\zhao\\Desktop\\fsdownload\\f.me")))) {// 将 ff 和 f 保存到数据流中((ExpressionFunction) ff).saveTo(objectOutput);((ExpressionFunction) f).saveTo(objectOutput);}}}
}
将文件保存的函数对象加载到库中
函数可以被序列化,当然也可以被反序列化,反序列化之后您可以将其注册到库中,也可以直接使用它!!!
package utils;import core.Mathematical_Expression;
import core.calculation.function.ExpressionFunction;
import core.calculation.function.ManyToOneNumberFunction;import java.io.IOException;
import java.io.ObjectInputStream;
import java.nio.file.Files;
import java.nio.file.Paths;public class MAIN {public static void main(String[] args) throws IOException {ManyToOneNumberFunction function;try (final ObjectInputStream objectInputStream = new ObjectInputStream(Files.newInputStream(Paths.get("C:\\Users\\zhao\\Desktop\\fsdownload\\f.me")))) {// 在这里读取到函数对象function = ExpressionFunction.readFrom(objectInputStream);}// 把函数注册回 Mathematical_ExpressionMathematical_Expression.register_function(function);// 也可以直接使用它final double run = function.run(1024);System.out.println(run);}
}
当然,反序列化也支持多个函数对象的加载,下面是一个示例
package utils;import core.Mathematical_Expression;
import core.calculation.function.ExpressionFunction;
import core.calculation.function.ManyToOneNumberFunction;import java.io.IOException;
import java.io.ObjectInputStream;
import java.nio.file.Files;
import java.nio.file.Paths;public class MAIN {public static void main(String[] args) throws IOException {ManyToOneNumberFunction ff, f;try (final ObjectInputStream objectInputStream = new ObjectInputStream(Files.newInputStream(Paths.get("C:\\Users\\zhao\\Desktop\\fsdownload\\f.me")))) {// 在这里读取到函数对象(要注意这里和保存时的顺序一致哦!!)// 如果要是不确定顺序,可以读取直接读取出来注册到库里 库会自动将函数的名称解析出来ff = ExpressionFunction.readFrom(objectInputStream);f = ExpressionFunction.readFrom(objectInputStream);}// 把函数注册回 Mathematical_ExpressionMathematical_Expression.register_function(ff);Mathematical_Expression.register_function(f);// 也可以直接使用它final double run = ff.run(1024);System.out.println(run);}
}
批量 序列化/注册 函数
在 1.3.4 版本中,您还可以直接在 Mathematical_Expression 中使用数据流的方式注册/序列化函数,这能够简化代码,下面是一个示例!
首先我们可以在这里将函数注册到库中!然后使用 Mathematical_Expression 来演示函数的序列化操作。
package utils;import core.Mathematical_Expression;
import core.calculation.function.Functions;
import core.calculation.function.ManyToOneNumberFunction;
import exceptional.WrongFormat;import java.io.FileOutputStream;
import java.io.IOException;@Functions({// 这里是需要被注册的两个函数 在这里标记一下 分别是 f 和 ff 以及 fff 几个函数"f(x) = x * x","ff(x) = f(x) + 1","fff(x) = x! + ff(x) + f(x)"
})
public class MAIN {public static void main(String[] args) throws IOException, WrongFormat {// 将函数注册一下Mathematical_Expression.register_function(MAIN.class);// 获取到 几个函数 的对象ManyToOneNumberFunction f = Mathematical_Expression.getFunction("f");ManyToOneNumberFunction ff = Mathematical_Expression.getFunction("ff");ManyToOneNumberFunction fff = Mathematical_Expression.getFunction("fff");// 直接将这几个函数输出到文件中try (final FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\zhao\\Desktop\\fsdownload\\f.ME")) {Mathematical_Expression.saveFunction(fileOutputStream, f, ff, fff);}}
}
接下来我们可以直接手动将文件读取到内存中并使用,在这里我们将演示 Mathematical_Expression 反序列化操作!
package utils;import core.Mathematical_Expression;
import core.calculation.function.ManyToOneNumberFunction;
import exceptional.WrongFormat;import java.io.FileInputStream;
import java.io.IOException;
import java.util.Map;public class MAIN {public static void main(String[] args) throws WrongFormat, IOException {// 将函数注册一下try (final FileInputStream fileInputStream = new FileInputStream("C:\\Users\\zhao\\Desktop\\fsdownload\\f.ME")) {// 直接在这里使用数据流来进行反序列化操作,这个数据流对应的文件包含的函数都会开始尝试注册final Map.Entry<Integer, Integer> integerIntegerEntry = Mathematical_Expression.register_function(fileInputStream);// 注册完毕之后在这里就可以查看到结果System.out.println("注册成功的数量:" + integerIntegerEntry.getKey());System.out.println("注册失败的数量:" + integerIntegerEntry.getValue());}// 然后我们就可以开始使用了 在这里的数据流中 包含的三个函数分别是 f ff ffffinal ManyToOneNumberFunction f = Mathematical_Expression.getFunction("f");final ManyToOneNumberFunction ff = Mathematical_Expression.getFunction("ff");final ManyToOneNumberFunction fff = Mathematical_Expression.getFunction("fff");System.out.println(f.run(10));System.out.println(ff.run(10));System.out.println(fff.run(10));}
}
下面是计算结果
[INFO][Calculation Management][24-03-22:01]] : A computing component is registered PrefixExpressionOperation
[INFO][Calculation Management][24-03-22:01]] : A computing component is registered BracketsCalculation2
[INFO][Calculation Management][24-03-22:01]] : A function is registered f
[INFO][Calculation Management][24-03-22:01]] : A function is registered ff
[INFO][Calculation Management][24-03-22:01]] : A function is registered fff
注册成功的数量:3
注册失败的数量:0
[INFO][Calculation Management][24-03-22:01]] : Get a function component from the manager. => f
[INFO][Calculation Management][24-03-22:01]] : Get a function component from the manager. => ff
[INFO][Calculation Management][24-03-22:01]] : Get a function component from the manager. => fff
[INFO][functionFormulaCalculation_temp][24-03-22:01]] : Use shared pool data. The identity of the data is: functionFormulaCalculation_temp(10.0*10.0)
100.0
[INFO][functionFormulaCalculation_temp][24-03-22:01]] : No Use shared pool: functionFormulaCalculation_temp(f(10.0) + 1)
[INFO][Calculation Management][24-03-22:01]] : Get a function component from the manager. => f
[INFO][functionFormulaCalculation_temp][24-03-22:01]] : Use shared pool data. The identity of the data is: functionFormulaCalculation_temp(10.0*10.0)
101.0
[INFO][functionFormulaCalculation_temp][24-03-22:01]] : No Use shared pool: functionFormulaCalculation_temp(10.0! + ff(10.0) + f(10.0))
[INFO][Calculation Management][24-03-22:01]] : Get a function component from the manager. => f
[INFO][functionFormulaCalculation_temp][24-03-22:01]] : Use shared pool data. The identity of the data is: functionFormulaCalculation_temp(10.0*10.0)
[INFO][Calculation Management][24-03-22:01]] : Get a function component from the manager. => ff
[INFO][functionFormulaCalculation_temp][24-03-22:01]] : Use shared pool data. The identity of the data is: functionFormulaCalculation_temp(f(10.0) + 1)
3629001.0
更多信息
- Switch to English Document
- mathematical-expression-py
- mathematical-expression-JS
- mathematical-expression-C++