Qt扩展-muParser数学公式解析

muParser数学公式解析

一、概述

muparser - Fast Math Parser Library

项目地址:https://beltoforion.de/en/muparser/features.php#idStart

muparser是一个高性能的数学计算表达式库,支持常用的函数、常用运算符、数学计算式的计算,这个库也提供了很多内置的功能、同时也开放了很多功能供用户使用。这个库使用的 C++语言、也可以用C语言搭配用、跨平台的支持

1. 针对速度进行了优化

  • 高解析性能;批量模式提供了表达式计算的并行化
  • 具有延迟计算的 If-Then-Else运算符
  • 在一次求值中计算多个逗号分隔子表达式:sin(X),x+y,x*x

2. 支持的运算符

  • 14个预定义运算符
  • 二元运算符是用户可定义的
  • 后缀运算符是用户可定义的
  • 中缀运算符是用户可定义的

3. 支持的函数

  • 25个预定义函数
  • 具有最多五个参数的固定数量
  • 具有可变数量的参数
  • 使用单个字符串参数(用于数据库查询)
  • 可以由用户扩展

4. 用户定义的常量

  • 数值常量
  • 字符串常量

5. 用户定义的变量

  • 在数量上无限
  • 可在解析器运行时由解析器定义:abc=123
  • 根据其他变量赋值变量是可能的

6. 自定义值识别回调

  • 我们可以定义值的外观
  • 我们可以让muparser读取十六进制值,如a=0x00ff00或二进制值
  • A=0b1000101
  • 我们还可以使用此功能从数据库中查询值

7. 其他功能

  • 使用后缀运算符作为单位乘数(3M->0.003)
  • 内置函数,用于对给定变量进行数值求导
  • 参数分隔符、小数分隔符、千位分隔符可以根据我们的区域设置进行调整
  • 基于CMake的构建系统
  • ISO 14882:符合2017年标准的代码
  • 每种语言都可以使用的DLL版本能够使用以C风格导出的函数

二、内置函数

下表概述了默认实现支持的函数,它列出了函数名称、参数数量和简短说明

名称 参数个数 解释
sin 1 正弦函数
cos 1 余弦函数
tan 1 切线函数
asin 1 反正弦函数
acos 1 反余弦函数
atan 1 圆弧正切函数
sinh 1 双曲正弦函数
cosh 1 双曲余弦
tanh 1 双曲正切函数
asinh 1 双曲弧正弦函数
acosh 1 双曲圆弧正切函数
atanh 1 双曲反正切函数
log2 1 以2为底的对数
log10 1 以10为底的对数
log 1 以e为底的对数为1(2.71828...)
ln 1 以e为底的1个对数(2.71828...)
exp 1 e的x次方
sqrt 1 平方根
sign 1 如果x<0,则符号1符号函数-1;如果x>0,则为1,阶跃函数
rint 1 舍入为最接近的整数
abs 1 绝对值
min var. 最小变量所有参数中的最小值
max var. 所有参数的最大值
sum var. 和变量所有参数的总和
avg var. 平均变量所有参数的平均值

三、内置二元运算符

下表列出了解析器支持的默认二进制运算符

操作符 描述 优先级
= 分配* 0
|| 逻辑或 1
&& 逻辑AND 2
| 按位或 3
& 按位和 4
<= 小于或等于 5
>= 大于或等于 5
!= 不等于 5
== 等于 5
> 大于 5
< 小于 5
+ 加法 6
- 减去 6
* 乘法 7
/ 除法 7
^ 将x乘以y的幂,幂运算符 8
  • *赋值运算符是特殊的,因为它更改了它的一个参数,并且只能应用于变量

四、三元运算符

Muparser内置了对If Then Else运算符的支持

它使用惰性求值,以确保只计算表达式的必要分支

操作符 描述 备注
?: If Then Else运算符 C++样式语法

五、内置常量

预定义常量名称的名称以下划线为前缀

解析器有两个预定义的常量:Pi和Eulers Number

常量定义的准确性最终取决于所选值类型(浮点型、双精度型、双精度长整型)的大小

常量 描述 备注
_pi 唯一的圆周率 3.141592653589793238462643
_e 欧拉数 2.718281828459045235360287

六、源码引入

1. 源码文件

官方建议将muparser直接嵌入到项目中将库源代码直接嵌入到客户端应用程序中是避免链接器冲突的最简单方法,这些冲突源于共享解析器库和项目使用的运行时库的不同版本

为了嵌入muparser,将以下文件包括到我们的项目中:

css 复制代码
muParser.cpp
muParserBase.cpp
muParserBytecode.cpp
muParserCallback.cpp
muParserError.cpp
muParserTokenReader.cpp

并确保在我们的项目包含路径中可以找到以下包含文件:

cpp 复制代码
muParser.h
muParserBase.h
muParserBytecode.h
muParserCallback.h
muParserDef.h
muParserError.h
muParserFixes.h
muParserTemplateMagic
muParserToken.h
muParserTokenReader.h

解析器类和所有相关类驻留在命名空间 mu 中,请确保添加一个 using

cpp 复制代码
using namespace mu;

添加到我们的文件中,或使用其完整名称引用所有类

2. 编译器开关

如果我们通过编译自己的版本或直接包含源代码来使用muParser,则可以使用一组预处理器定义来定制其行为

以下定义位于文件muParserDef.h中:

1. MUP_BASETYPE

宏 MUP_BASETYPE 定义muParser使用的底层数据类型这可以是任何浮点值类型(浮点型、双精度型或双精度长整型)宏默认为双精度,如果我们需要更高的精度或希望将muParser Seamless与使用Float作为其数据类型的客户端代码一起使用,请修改此值

cpp 复制代码
#define MUP_BASETYPE double

2.MUP_USE_OPENMP

如果我们使用的是CMake构建系统,则使用-DENABLE_OPENMP=OFF/ON选项激活OpenMP支持

该选项将为我们设置宏MUP_USE_OPENMP,并自动链接到OpenMP,启用OpenMP支持时,批量模式下的表达式求值将在多个CPU上并行执行默认情况下,使用CMake构建时,OpenMP支持处于活动状态

cpp 复制代码
#define MUP_USE_OPENMP

如果不是使用CMake构建,并且已将源代码直接嵌入到项目中,请取消对文件muParserDef.h中宏的注释

根据硬件的不同,并行化可以显著提高解析器的速度(30%-400%)

启用并行化对简短表达式没有显著影响

3. MUP_STRING_TYPE

这个定义决定了muParser使用的字符串类型,它可以是 std::string,也可以是 std::wstring,这个定义不应该直接设置

如果存在预处理器MACRO_UNICODE,则将其定义为 std::wstring

cpp 复制代码
#define MUP_STRING_TYPE std::wstring

七、实例

cpp 复制代码
#include "muParser.h"

double fVal;
try
{
	double result = 0;
	
	// 定义对象
	mu::Parser m_parser;
	
	// 定义可能需要的变量
	double x_value = 7.434, y_value = 4.5, result;

    paser.DefineVar(L"x", &x_value);
    paser.DefineVar(L"y", &y_value);
	
	// 设置数学表达式
	m_parser.SetExpr("4.54534*(5.43-0.689*_pi)^2");
	
	// 计算
	result = m_parser.Eval();

	// 设置数学表达式
	m_parser.SetExpr(L"x^y+5.654-534.432^y");

	// 计算
	result = m_parser.Eval();
	
	return result;
}
catch (Parser::exception_type &e)
{
  std::cout << e.GetMsg() << endl;
}

更多就需要去其官网查看说明、配合着源代码一起使用。

相关推荐
ao_lang2 天前
剑指offer第五天
python·算法·cpp
相隔一个图书馆的距离4 天前
redis源码系列--(二)--multi/exec/eval命令执行流程
数据库·redis·缓存·exec·eval·multi
习惯就好zz14 天前
windows msvc2017 x64编译AWS SDK CPP库
sdk·aws·cpp·1024程序员节
深耕AI21 天前
新版Win32高级编程教程-学习笔记01:应用程序分类
microsoft·visual studio·cpp
LyaJpunov22 天前
B+树的原理图解
数据结构·b树·cpp
Mike!2 个月前
C++进阶 set和map讲解
java·开发语言·数据结构·c++·set·map·cpp
小妖剑2 个月前
位运算:带带孩子吧,孩子很强的!
c++·性能优化·二进制·位运算·cpp
原来452 个月前
如何学习 5GC 和 IMS (以及 C++ 就业方向)
信息与通信·ims·cpp·通信·5gc
jjb-coder3 个月前
Qt-信号与槽机制
qt·cpp·底层
睡觉待开机3 个月前
【practise】栈的压入和弹出序列
开发语言··cpp