mathematical-expression-cpp | C++ 数学表达式解析库

image 数学表达式-cpp

  • Switch to English Document

介绍

本框架是一种针对数学公式解析的有效工具,能够通过C++的API解析包含嵌套函数,包含函数,数列步长累加等数学公式,返回值是一个数值的结果对象,同时也可以进行比较运算的操作,再进行比较的时候,返回值是一个布尔值结果对象。
如果您是一位 Java 或 python爱好者,可以专门前往 JavaAPI
或 PythonAPI 中进行相关资料的查阅。

如何在 Windows 中使用库?

我们已经预编译好了 Windows 版本的DLL,在项目中有一个 include
文件目录,其中存储的就是库需要的所有头文件,您可以将其中的库文件导入到您的项目中,然后再集成本框架编译好的dll,下面是cmake的配置文件实例。

cmake_minimum_required(VERSION 3.23)
project(MyCpp)

set(CMAKE_CXX_STANDARD 14)

# 设置头文件目录(可以自定义)
include_directories(${PROJECT_SOURCE_DIR}/head)
add_executable(MyCpp main.cpp)
# 与项目进行链接(将库链接到编译之后的目标中)
target_link_libraries(${PROJECT_NAME} D:\\liming\\Project\\Clion\\MyCpp\\cmake-build-debug\\mathematical_expression_cpp.dll)

集成操作完毕之后,您可以尝试输入以下代码来判断库的功能是否正常,下面是该库的一个测试代码,如果其运行之后的程序main函数返回值为0
代表程序正常退出,意味着库装载完毕。

#include "mathematical_expression.h"

int main(){
    system("chcp 65001");
    // 打印 mathematical_expression 的版本信息
    cout << mathematical_expression::getVERSION() << endl;
}

如何在 Linux 中使用库?

针对 Linux 系统的多样性,我们难以提供一种符合大部分系统架构的 dll
库文件,但是您无需担心,此库没有任何的第三方依赖,仅仅运行于本地库中,这对于它的源码编译工作来说是一个好消息,您可以访问我们写好的《在 Linux 环境中编译 C++ 源码》
,根据文章的引导来进行编译工作。
当然,您也可以通过扫描二维码来阅读文章,这对于一些操作会更加简单。
在这里插入图片描述

通过 mathematical-expression 库直接获取到计算组件并进行计算

#include "mathematical_expression.h"

int main(){
    system("chcp 65001");
    // 构建需要计算的两种表达式
    string s1 = "1 + 20 - 2 + 4", s2 = "1 + 20 - (2 + 4)";
    // 获取到 me 门户类
    mathematical_expression me;
    // 获取到 无括号表达式计算组件
    ME::PrefixExpressionOperation prefixExpressionOperation = me.getPrefixExpressionOperation();
    // 获取到 有括号表达式计算组件
    ME::BracketsCalculationTwo bracketsCalculationTwo = me.getBracketsCalculation2();
    // 开始检查表达式
    prefixExpressionOperation.check(s1);
    bracketsCalculationTwo.check(s2);
    // 开始计算两个表达式 可以使用左移运算符将表达式送给计算组件 获取到结果对象
    ME::CalculationNumberResults r1 = prefixExpressionOperation << s1;
    ME::CalculationNumberResults r2 = bracketsCalculationTwo << s2;
    // 开始进行结果查看
    cout << "计算层数:" << r1.getResultLayers() << "\t计算结果:" << r1 << "\t计算来源:" << r1.getCalculationSourceName() << endl;
    cout << "计算层数:" << r1.getResultLayers() << "\t计算结果:" << r2 << "\t计算来源:" << r1.getCalculationSourceName() << endl;
}
  • 运行结果
Active code page: 65001
计算层数:1     计算结果:23    计算来源:PrefixExpressionOperation
计算层数:1     计算结果:15    计算来源:PrefixExpressionOperation

进程已结束,退出代码0

框架架构

门户类

我们可以通过指定的门户类对象获取到相关的各个计算组件,这里与 JavaAPI 和 PythonAPI 的实现有些不同,这里是使用的get函数获取到指定计算组件对象,而非使用
Hash 缓冲池。

#include "mathematical_expression.h"

int main(){
    system("chcp 65001");
    // 获取到 me 门户类
    mathematical_expression me;
    // 获取到 无括号表达式计算组件
    ME::PrefixExpressionOperation prefixExpressionOperation = me.getPrefixExpressionOperation();
    // 获取到 有括号表达式计算组件
    ME::BracketsCalculationTwo bracketsCalculationTwo = me.getBracketsCalculation2();
}

计算组件

无括号表达式

  • 类组件:ME::PrefixExpressionOperation

  • 介绍

    针对一个没有括号,但是有加减乘除以及取余等运算操作的数学表达式而设计的组件,该组件可以实现带有优先级计算的功能,其中通过前缀表达式解析计算,将操作数与操作符一同存储到栈,在存储的同时配有计算优先级比较,如果当下的优先级较小,就先将上一个操作数与操作符与当前操作数进行运算,形成一个新的数值,然后再入栈。

  • API使用示例

    该组件支持的运算符有: a+b a-b a*b a/b a%b a^b

#include "mathematical_expression.h"

int main(){
    system("chcp 65001");
    // 获取到 me 门户类
    mathematical_expression me;
    // 获取到 无括号表达式计算组件
    ME::PrefixExpressionOperation prefixExpressionOperation = me.getPrefixExpressionOperation();
    // 构建一个表达式
    string s = "1 + 2 + 4 * 10 - 3";
    // 开始检查表达式
    prefixExpressionOperation.check(s);
    // 开始计算两个表达式 可以使用左移运算符将表达式送给计算组件 获取到结果对象
    ME::CalculationNumberResults r1 = prefixExpressionOperation << s;
    // 开始进行结果查看
    cout << "计算层数:" << r1.getResultLayers() << "\t计算结果:" << r1 << "\t计算来源:" << r1.getCalculationSourceName() << endl;
}
  • 运行结果

    在API调用中,对函数的运行结果进行了打印,可以看到,组件计算的返回值是一个结果集对象,在该对象中存储的就是很多有关计算结果相关的信息。

Active code page: 65001
计算层数:1     计算结果:40    计算来源:PrefixExpressionOperation

进程已结束,退出代码0

嵌套括号表达式

  • 类组件:ME::BracketsCalculation2

  • 介绍:

    嵌套括号表达式解析组件,能够针对带有多个括号的数学表达式进行解析与结果计算,针对嵌套括号进行优先级的解析与计算,该组件依赖于“core.calculation.number.PrefixExpressionOperation”,在该组件中采用递归进行括号的解析,然后将最内层面的表达式提供给“core.calculation.number.PrefixExpressionOperation”进行计算。

  • API使用示例

    该组件支持的运算符有: a+b a-b a*b a/b a%b ( )

#include "mathematical_expression.h"

int main(){
    system("chcp 65001");
    // 获取到 me 门户类
    mathematical_expression me;
    // 获取到 无括号表达式计算组件
    ME::BracketsCalculationTwo bracketsCalculationTwo = me.getBracketsCalculation2();
    // 构建一个表达式
    string s = "1 + 2 + 4 * (10 - 3)";
    // 开始检查表达式
    bracketsCalculationTwo.check(s);
    // 开始计算两个表达式 可以使用左移运算符将表达式送给计算组件 获取到结果对象
    ME::CalculationNumberResults r1 = bracketsCalculationTwo << s;
    // 开始进行结果查看
    cout << "计算层数:" << r1.getResultLayers() << "\t计算结果:" << r1 << "\t计算来源:" << r1.getCalculationSourceName() << endl;
}
  • 运行结果

    在API调用中,对表达式的计算结果进行了打印,可以看到,组件计算的返回值是一个数值结果对象,在该对象中存储的就是很多有关计算结果相关的信息。

Active code page: 65001
计算层数:2     计算结果:31    计算来源:BracketsCalculation

进程已结束,退出代码0

区间累加表达式

  • 类组件:ME::CumulativeCalculation

  • 介绍

    在数学表达式中,往往有这样的一种公式,公式内容如下图所示,可以看到需要进行累加的数列操作,那么在这种公式的需求下,您可以通过上面的类组件去达到您所需要的目的。
    img_1

  • API使用示例

    语法层面于其他组件几乎一致,数学表达式的撰写于组件的计算示例就如下面所示,在这里展示的就是一个累加数学公式的计算。

#include "mathematical_expression.h"
int main() {
    system("chcp 65001");
    // 创建数学表达式解析库对象
    mathematical_expression me;
    // 获取一个计算累加数学表达式的组件
    ME::CumulativeCalculation cumulativeCalculation = me.getCumulativeCalculation();
    // 构建一个数学表达式,这里的"n[1,10,1]"就类似数学中的累加符号,n会在这个区间内不断增加,每增加一次都会被带入公式中计算一次
    // 其中[1,10,1]中的最后一个1 代表增加步长,能够实现区间内不同等差值的累加
    string s = "n[1,10,1] 2 * (n + 1)";
    // 检查数学表达式
    cumulativeCalculation.check(s);
    // 计算结果
    ME::CalculationNumberResults results = cumulativeCalculation << s;
    // 将结果打印出来
    cout << "计算层数:" << results.getResultLayers() << "\t计算结果:" << results << "\t计算来源:" << results.getCalculationSourceName() << endl;
}
  • 运行结果
Active code page: 65001
计算层数:11    计算结果:130   计算来源:CumulativeCalculation

进程已结束,退出代码0

函数运算表达式

  • 类组件:ME::FunctionFormulaCalculation

  • 介绍

    针对一些函数的操作,在该框架中也有支持,可以使用上面的类进行这中需要函数的数学表达式的书写,需要注意的是,一切在表达式中使用到的函数都需要在“CalculationManagement”中进行逻辑注册,使得计算的时候可以访问到函数

  • API使用示例

#include <mathematical_expression.h>
#include "FunctionManager.h"
int main() {
    system("chcp 65001");
    // 准备函数 这里的函数的作用是将参数 * 2
    auto myFun = [](const double *v) {
        return *v * 2;
    };
    // 注册函数 将我们的函数注册成为 DoubleValue 的名称
    ME::FunctionManager::append("DoubleValue", myFun);
    // 构建一个数学表达式,表达式中使用到了函数 DoubleValue
    string s = "2 * DoubleValue(2 + 3) + 1";
    // 获取到 数学表达式解析库
    mathematical_expression me;
    // 获取到函数表达式计算组件
    auto functionFormulaCalculation = me.getFunctionFormulaCalculation();
    // 检查数学表达式
    functionFormulaCalculation.check(s);
    // 计算出结果
    ME::CalculationNumberResults results = functionFormulaCalculation << s;
    // 将结果打印出来
    cout << "计算层数:" << results.getResultLayers() << "\t计算结果:" << results << "\t计算来源:" << results.getCalculationSourceName() << endl;
}
  • 运行结果
Active code page: 65001
计算层数:1     计算结果:21    计算来源:BracketsCalculation

进程已结束,退出代码0
注意事项

1.0.2 版本中 针对函数的注册操作不能向后兼容,如果是在1.0.2版本以以后的版本 请使用下面的方式注册函数

    // 准备函数 将函数的形参类型 由 double* 更改为 ME::MEStack<double> 即可 因为 ME::MEStack<double> 具有更大的灵活性
auto myFun =[](const ME::MEStack<double>& v) {
double res = 0;
for (int i = 0; i < v.size(); ++i){
res += v.get(i);
}
return res;
};
// 注册函数 将我们的函数注册成为 DoubleValue 的名称
ME::FunctionManager::append("sum", myFun);

函数多参数运算表达式

  • 类组件:ME::FunctionFormulaCalculationTwo
  • 介绍

针对一些在表达式中使用了函数的表达式计算,可以使用上面的类进行操作,它是“core.calculation.number.FunctionFormulaCalculation”类的升级版,从1.0.2版本开始出现,同时也是它的一个子类拓展实现。

相较于父类,本组件弥补了父类只能解析带有一个参数函数表达式的不足,在该组件中,可以使用很多的实参进行函数的运算,例如sum(
1,2,3) 这类函数,就是一个多参函数,接下来请看API的使用示例,在此示例中,展示了多惨函数表达式的计算与结果。

  • API使用示例
#include <mathematical_expression.h>
#include "FunctionManager.h"
int main() {
    system("chcp 65001");
    // 准备函数 这里的函数的作用是将 3 个参数求和
    auto myFun = [](const ME::MEStack<double>& v) {
        double res = 0;
        for (int i = 0; i < v.size(); ++i){
            res += v.get(i);
        }
        return res;
    };
    // 注册函数 将我们的函数注册成为 DoubleValue 的名称
    ME::FunctionManager::append("sum", myFun);
    // 构建一个数学表达式,表达式中使用到了函数 DoubleValue
    string s = "2 * sum(2 + 3, 1 + 20, 10 + (1 - 2)) + 1";
    // 获取到 数学表达式解析库
    mathematical_expression me;
    // 获取到函数表达式计算组件
    auto functionFormulaCalculation = me.getFunctionFormulaCalculation2();
    // 检查数学表达式
    functionFormulaCalculation.check(s);
    // 计算出结果
    ME::CalculationNumberResults results = functionFormulaCalculation << s;
    // 将结果打印出来
    cout << "计算层数:" << results.getResultLayers() << "\t计算结果:" << results << "\t计算来源:" << results.getCalculationSourceName() << endl;
}
  • 运行结果
Active code page: 65001
计算层数:1     计算结果:71    计算来源:BracketsCalculation

进程已结束,退出代码0

快速区间求和计算组件(基于括号表达式)

  • 类组件:ME::FastSumOfIntervalsBrackets.py

  • 介绍

    1.15版本的新产物,区间快速求和组件,是针对一个等差为1的区间进行所有元素求和的快速组件,它将一个区间在逻辑上模拟成为一个数学数列,并通过求和公式进行快速的求和。

    该组件实现了共享池计算功能,将检查,计算,以及上一次结果记录实现,能够加快计算速度,具体API调用如下所示。

#include "mathematical_expression.h"

int main() {
    system("chcp 65001");
    // 获取到数学表达式解析库对象
    mathematical_expression me;
    // 获取到区间累加表达式对象
    ME::FastSumOfIntervalsBrackets fastSumOfIntervalsBrackets = me.getFastSumOfIntervalsBrackets();
    // 准备需要被计算的数学表达式,这里的数学表达式中有个逗号,逗号两边代表的就是区间的两个边界
    string f1 = "1 + 10, 20 - (5 + 2)";
    // 检查数学表达式
    fastSumOfIntervalsBrackets.check(f1);
    // 将步长修改为 2
    fastSumOfIntervalsBrackets.step = 2;
    // 开始计算 并获取到结果对象
    ME::CalculationNumberResults r1 = fastSumOfIntervalsBrackets << f1;
    // 开始进行结果查看
    cout << "计算层数:" << r1.getResultLayers() << "\t计算结果:" << r1 << "\t计算来源:" << r1.getCalculationSourceName()
         << endl;
}
  • 运行结果 从上面代码中我们可以看到,快速区间求和计算的公式由被逗号分割的两个括号表达式组成
Active code page: 65001
计算层数:1     计算结果:24    计算来源:FastSumOfIntervalsBrackets

进程已结束,退出代码0

数学函数表达式的注册与使用

#include <mathematical_expression.h>
#include "FunctionManager.h"
#include "ExpressionFunction.h"
#include "MEStack.h"

int main() {
    system("chcp 65001");
    // 这里的函数的作用是将 3 个参数求和
    // 注册函数 将我们的函数注册成为 DoubleValue 的名称
    ME::FunctionManager::append("sum(a,b,c) = a + b + c");
    // 构建一个数学表达式,表达式中使用到了函数 DoubleValue
    string s = "2 * sum(2 + 3, 1 + 20, 10 + (1 - 2)) + 1";

    // 获取到 数学表达式解析库
    mathematical_expression me;
    cout << "开始计算" << endl;

    // 获取到函数表达式计算组件
    auto functionFormulaCalculation = me.getFunctionFormulaCalculation2();
    // 检查数学表达式
    functionFormulaCalculation.check(s);
    // 计算出结果
    ME::CalculationNumberResults results = functionFormulaCalculation << s;
    // 将结果打印出来
    cout << "计算层数:" << results.getResultLayers() << "\t计算结果:" << results << "\t计算来源:"
         << results.getCalculationSourceName() << endl;

    // 也可以手动获取到函数对象
    auto f = ME::FunctionManager::getFunction("sum");
    ME::MEStack<double> meStack;
    meStack.push(1);
    meStack.push(2);
    meStack.push(3);
    cout << f(meStack) << endl;
}

C++API 特性

在 C++ 中,库具有更快的解析与计算速度,同时其具有更加庞大的功能,接下来针对C++中的特有功能来进行一个说明。

操作数之间的计算操作

通过计算组件计算出来的结果对象,其还具有运算功能,可以基于此方式来进行多个操作数之间的计算操作,接下来就是一个示例。

#include <mathematical_expression.h>

int main() {
    // 准备数学表达式对象
    mathematical_expression me;
    // 打印出数学表达式库的版本号
    std::cout << mathematical_expression::getVERSION() << endl;
    // 准备要被计算的数学表达式
    std::string f = "1 + (3 - 2) + 10";
    // 准备计算组件
    ME::BracketsCalculationTwo bracketsCalculationTwo = me.getBracketsCalculation2();

    // 开始进行计算
    ME::CalculationNumberResults res1 = bracketsCalculationTwo << f;
    // 使用结果对象进行计算
    ME::CalculationNumberResults res2 = res1 + res1;
    std::cout << "res1 + res1 = " << res2 << "\t其结果的源 = " << res2.getCalculationSourceName() << endl;
}
  • 运行结果
1.0.1-mathematical_expression-C++
res1 + res1 = 24        其结果的源 = (BracketsCalculation + BracketsCalculation)

进程已结束,退出代码0

操作数中的别名操作

在经过计算组件计算之后,操作数中包含计算组件的类型名称,但是在C++中,由于有了操作数之间的计算特性,源名称就显得很混乱,因此可以使用下面的操作起别名称,这样就可以达到良好的效果。

接下来是一个有关别名操作的基本示例

#include <mathematical_expression.h>

int main() {
    // 准备数学表达式对象
    mathematical_expression me;
    // 打印出数学表达式库的版本号
    std::cout << mathematical_expression::getVERSION() << endl;
    // 准备要被计算的数学表达式
    std::string f = "1 + (3 - 2) + 10";
    // 准备计算组件
    ME::BracketsCalculationTwo bracketsCalculationTwo = me.getBracketsCalculation2();

    // 开始进行计算
    ME::CalculationNumberResults res1 = bracketsCalculationTwo << f;
    // 打印出结果对象的源名称
    std::cout << res1.getCalculationSourceName() << endl;
    // 为 res1 设置别名
    res1.as("res1");
    // 再一次打印出结果对象的源名称
    std::cout << res1.getCalculationSourceName() << endl;
}
  • 运行结果
1.0.0-mathematical_expression-C++
BracketsCalculation
res1

进程已结束,退出代码0

接下来是一个有关别名操作的有趣案例(操作数之间的计算 + 别名)

#include <mathematical_expression.h>

int main() {
    // 准备数学表达式对象
    mathematical_expression me;
    // 打印出数学表达式库的版本号
    std::cout << mathematical_expression::getVERSION() << endl;
    // 准备要被计算的数学表达式
    std::string f = "1 + (3 - 2) + 10";
    // 准备计算组件
    ME::BracketsCalculationTwo bracketsCalculationTwo = me.getBracketsCalculation2();

    // 开始进行计算
    ME::CalculationNumberResults res1 = bracketsCalculationTwo << f;
    // 为 res1 设置别名
    res1.as("res1");
    std::cout << res1 << endl;

    // 计算出 res2
    ME::CalculationNumberResults res2 = res1 + res1;
    // 为 res2 设置别名
    res2.as("res2");
    std::cout << res2 << endl;
    std::cout << res2.getCalculationSourceName() << endl;

    // 计算出 res3 在这里使用结果对象之间的运算操作,res3 = res2 - res1
    ME::CalculationNumberResults res3 = res2 - res1;
    std::cout << '[' << res3  << ']' << '\t' << res3.getCalculationSourceName() << endl;

    // 计算出 res4 在这里使用结果对象之间的运算操作,res4 = res3 * res1 = (res2 - res1) * res1
    ME::CalculationNumberResults res4 = res3 * res1;
    std::cout  << '[' << res4 << ']' << '\t' << res4.getCalculationSourceName() << endl;
}
  • 运行结果
1.0.0-mathematical_expression-C++
12
24
res2
[12]    (res2 - res1)
[144]   ((res2 - res1) * res1)

进程已结束,退出代码0

更多信息

  • date: 2023-06-20
  • Switch to English Document
  • mathematical-expression-Java
  • mathematical-expression-py

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/708475.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python学习从0开始——Kaggle深度学习002

Python学习从0开始——Kaggle深度学习002 一、单个神经元1.深度学习2.线性单元示例 - 线性单元作为模型多个输入 3.Keras中的线性单元 二、深度神经网络1.层多种类型的层 2.激活函数3.堆叠密集层4.构建Sequential模型 三、随机梯度下降1.介绍2.损失函数3.梯度下降法1.梯度下降法…

只登录不发微博ip地址会变吗?探索其中的奥秘

在数字化时代&#xff0c;网络IP地址如同我们的数字身份证&#xff0c;记录着我们在网络世界中的每一次活动。对于微博这一社交平台的用户而言&#xff0c;IP地址的变动或许是他们未曾注意过的细节。那么&#xff0c;当用户仅登录微博而不发微博时&#xff0c;其IP地址是否会发…

仰望U8三大黑科技,重新定义智能汽车

文 | 智能相对论 作者 | 雷歌 是时候重新定义中国的“智能汽车”了。 在仰望U8出来以前&#xff0c;普通人对知道的智能汽车的配置认识&#xff0c;智能汽车是智能驾驶智能座舱&#xff0c;硬件上大概是这几样&#xff1a;毫米波雷达激光雷达智驾芯片。 仰望U8出来以后&…

Spring Boot集成 Spring Retry 实现容错重试机制并附源码

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

LDO重要参数 – 芯片热阻

原文出自微信公众号【小小的电子之路】 最近画了一块电路板&#xff0c;板子上的芯片采用LDO供电&#xff0c;测试过程中发现LDO发热极其严重&#xff0c;最终不得不重新画板&#xff0c;加入散热设计。提到芯片发热&#xff0c;不得不说的一个参数就是芯片热阻&#xff0c;LDO…

PyTorch -- Visdom 快速实践

安装&#xff1a;pip install visdom 注&#xff1a;如果安装后启动报错可能是 visdom 版本选择问题 启动&#xff1a;python -m visdom.server 之后打开出现的链接 http://localhost:8097Checking for scripts. Its Alive! INFO:root:Application Started INFO:root:Working…

安装前端依赖node-sass报错

文章目录 问题1&#xff1a;node-sass报错问题2&#xff1a;node-gyp报错问题3&#xff1a;node-sass再次报错问题4&#xff1a;node-sass三次报错 问题1&#xff1a;node-sass报错 问题描述&#xff1a;经常会碰到一个新的项目安装依赖时&#xff0c;会报node-sass版本的问题…

寄件管理系统操作教程

步入信息化时代&#xff0c;企业之间的经济活动开始向线上转移&#xff0c;对公邮寄的管理问题&#xff0c;也开始进入管理者的视线内。为什么这么说呢&#xff1f; 很简单&#xff0c;早前想要谈妥一单生意&#xff0c;需要会面拜访等等线下活动&#xff0c;随着互联网的发展&…

你好,Jetpack Compose

文章目录 为什么选 Jetpack Compose先决条件新建项目新建虚拟设备运行项目 为什么选 Jetpack Compose Jetpack Compose 是 Android 开发最新的、现代化的 UI 框架开发者几乎只需要使用 Kotlin 一门语言即可完成 App 开发&#xff08;Java 是基础&#xff0c;有些源码是 Java 写…

无线MODBUS通讯模块在供水系统中的应用

一、项目背景 我国是人口大国、农业大国&#xff0c;同时也是贫水大国。由于大量工业废水污染了部分河流、地表的浅层水资源&#xff0c;并且有逐年加重的趋势&#xff0c;再加上农业、绿化等灌溉对水资源的大量消耗&#xff0c;这些因素综合作用进一步加剧了我国水资源紧缺的…

Seate分布式锁

XA模式 在第一阶段资源协调者&#xff08;TC&#xff09;会向资源管理者&#xff08;RM&#xff09;发出一个准备的请求&#xff0c;RM开始处理自身的业务&#xff0c;处理完成后不提交事务&#xff0c;而是向TC响应一个执行结果&#xff0c;表明自己成功还是失败&#xff0c;如…

解析Facebook对当代文化传播的影响力

Facebook作为全球最大的社交媒体平台之一&#xff0c;承载着巨大的文化传播功能&#xff0c;对当代文化产生了深远的影响。从社会交流、价值观念到艺术创作和政治动态&#xff0c;Facebook已经成为了人们获取信息、表达观点和交流想法的重要平台。本文将深入解析Facebook对当代…

watcher学习小结

架构 主要是watcher-api&#xff0c;watcher-applier&#xff0c;watcher-decision-engine watcher-applier watcher-decision-engine 将DecisionEngineManager和DecisionEngineSchedulingService封装到oslo_service&#xff0c;然后调service的launch_service&#xff0c;实…

Unity接入PS5手柄和Xbox手柄以及Android平台的(以及不同平台分析)

Unity接入PS5手柄和Xbox手柄以及Android平台的&#xff08;以及不同平台分析&#xff09; 介绍Unity手柄小知识PC端和编辑器上的摇杆事件和滑动事件PS5手柄Xbox手柄北通手柄 安卓环境下&#xff08;安卓手机或者安卓模拟器&#xff09;PS5手柄Xbox手柄北通手柄 总结 介绍 最近…

最好用的邮箱管理软件推荐,邮箱管理软件哪个好?(干货篇)

在快节奏的工作与生活中&#xff0c;有效管理电子邮件成为提升个人与团队效率的关键。 面对海量信息流&#xff0c;一款好的邮箱管理软件不仅能够帮助我们高效地整理收件箱&#xff0c;还能确保重要邮件不会错过&#xff0c;同时提升通讯的便捷性和安全性。 本文将为您推荐几款…

【Java】解决Java报错:FileNotFoundException

文章目录 引言1. 错误详解2. 常见的出错场景2.1 文件路径错误2.2 文件名拼写错误2.3 文件权限问题2.4 文件路径未正确拼接 3. 解决方案3.1 检查文件路径3.2 使用相对路径和类路径3.3 检查文件权限3.4 使用文件选择器 4. 预防措施4.1 使用配置文件4.2 使用日志记录4.3 使用单元测…

浅谈TARA在汽车网络安全中的关键角色

随着现代汽车技术的迅猛发展&#xff0c;网络安全成为汽车行业一个不可忽视的领域。为了应对日益复杂的网络威胁&#xff0c;ISO/SAE 21434标准和UN R155法规提供了系统化的网络安全管理框架。其中&#xff0c;TARA&#xff08;威胁分析与风险评估&#xff09;作为核心方法论&a…

UE5-不同材质上脚步声

主要是用物理材质给不同的材质加一个标签 创建材质 首先去设置里面创建几个地形材质名称&#xff0c;我这里创建了Grass&#xff0c;Rock&#xff0c;Wood&#xff0c;Water &#xff08;就是名字而已&#xff09; 然后创建物理材质&#xff08;物理材质可以添加到现有的普通…

使用ZIP包安装MySQL及配置教程

在本教程中&#xff0c;我们将指导您完成使用ZIP包安装MySQL的过程&#xff0c;并对配置文件进行必要的修改&#xff0c;以及解决可能遇到的问题。本示例以MySQL 5.7.44为例&#xff0c;但步骤同样适用于其他版本如MySQL 8.3.0等。请根据实际需要选择适合的版本下载&#xff1a…

语法08 C++ 数据类型之间的强制转换

强制类型转换 强制类型转换&#xff0c;就是把一种数据类型转化为另一种指定的数据类型。 它是一种临时的转换。 强制类型转换格式 格式&#xff1a;(数据类型) (表达式) 即&#xff1a;(要被转换成的类型&#xff09;&#xff08;被转换的式子&#xff09;; 注意&#x…