C++程序设计:原理与实践(进阶篇)16.5 数值算法

简介:

16.5 数值算法


大多数的标准库算法都涉及处理数据管理问题:它们需要对数据进行拷贝、排序、查找等。但是,只有少数算法涉及数值计算。当我们需要进行计算时,这些数值算法就变得十分重要了,并且这些算法为我们在STL框架中编写数值算法提供了范例。

在STL标准库中只有四种数值算法:

数值算法

x = accumulate(b,e,i) 累加序列中的值;例如,对{a, b, c, d}计算i+a+b+c+d。结果x的类型与初始值i的类型一致

x = inner_product(b,e,b2,i) 将两个序列的对应元素相乘并将结果累加。例如,对{a, b, c, d}和{e, f, g, h}计算i+a·e+b·f+c·g+d·h。结果x的类型与初始值i的类型一致

r = partial_sum(b,e,r) 对一个序列的前n个元素进行累加,并将累加结果生成一个序列。例如,对{a, b, c, d}将生成{a, a+b, a+b+c, a+b+c+d}

r = adjacent_difference(b,e,b2,r) 对一个序列的相邻元素进行减操作,并将得到的差生成一个序列。例如,对{a, b, c, d}将生成{a, b-a, c-b, d-c}

 

这些算法可以在<numeric>中找到。我们将介绍前两个,如果你觉得有需要的话,可以自己去查阅其他两个的详细情况。

16.5.1 累积

accumulate()是最简单但最有用的数值算法。在其最简单的形式中,该算法将一个序列中的值进行累加:

 

给定初始值init,该算法将序列[f?irst:last)中的每个值加到init上,并将和返回。init通常被称为累加器。例如:

 

这段代码将打印15,即0+1+2+3+4+5(0是初始值)。显然,accumulate()能够被用于所有类型的序列:

 

结果(和)的类型与accumulate()用来保存累加器的变量的类型一致。这带来了一定的灵活性,这可能是十分重要的,例如:

 

在一些计算机上long的有效位数要比int更多。与int型相比,double能够表示更大范围的数,但可能精度更差。我们将在第24章中再讨论范围和精度在数值计算中所起的作用。

将保存结果的变量用作初始值是一种常见的指明累加器类型的方法:

 

记住:要初始化累加器并将accumulate()的结果保存在这个变量中。在本例中,s2在初始化之前就用作了初始化器,因此算法的结果是未定义的。我们将s3传递给accumulate()(传值方式,参见8.5.3节),但算法结果并未被保存,这只是浪费时间。

16.5.2 泛化accumulate()

基本的三参数accumulate()版本执行累加运算。但是,我们可能还想在序列上执行很多其他有用的运算,例如乘法和减法。为此,STL提供了另一个四参数的accumulate()版本,允许我们指定要执行的运算:

 

任何接受两个累加器类型实参的操作均能用于这一版本的accumulate()。例如:

 

这段代码将打印35.1384,即1.0×1.1×2.2×3.3×4.4(1.0为初始值)。这里提供的二元运算符multiplies<double>()是一个实现乘法运算的标准库函数对象;multiplies<double>实现double的乘法;multiplies<int>实现int的乘法,等等。还有一些其他的二元函数对象:plus(加法),minus(减法),divides,modulus(取余)。这些对象均在<functional>中定义(见附录C.6.2)。

注意,为了计算浮点数的积,初始值显然应设为1.0。

如sort()例子(见16.4.2节)中所示,我们常常对类对象中包含的数据更感兴趣,而不仅仅是普通内置类型。例如,给定物品的单位价格和单位数,我们可能想要计算所有物品的价值总和:

 

我们可以让accumulate的运算符从一个Record元素中抽取units,将其与单位价格相乘并加到累加器中:

 

我们在这里很“懒惰”,使用了函数而不是函数对象——这仅仅是为了展示可以这么做。我们倾向于优先选用函数对象:

如果需要在调用之间保存值;

或者,如果代码很短以致内联化会带来很大不同(至多是几个原语操作)。

基于第二个原因,我们应该在本例中选用函数对象。

试一试

定义一个vector<Record>,用你所选择物品的四个记录将其初始化,并用上面的函数计算物品的总价值。

16.5.3 内积

给定两个向量,将它们对应位置的元素相乘并将结果累加,这一运算称为向量的内积(inner product),内积在很多领域都十分有用(例如物理和线性代数,参见24.6节)。如果你更喜欢代码而不是文字,下面就是STL版本:

 

这段代码将内积的概念推广到任意元素类型的任何序列。以股票市场指数为例。在股票市场中,每一上市公司都会被分配一个“权重”。例如,在道琼斯工业指数中,我们看到Alcoa公司的最新权重为2.4808。为了获得当前的指数值,我们将每个公司的股票价格与其权重相乘,并将所得所有加权价格相加。显然,这就是价值和权重的内积。例如:

 

 

注意,inner_product()处理两个序列。但它只接受三个参数,对于第二个序列只描述了开始位置。算法假设第二个序列包含的元素个数要等于或多于第一个序列。如果这一假设不成立,将产生运行时错误。对于inner_product()而言,第二个序列包含更多元素是没问题的,那些“多余的元素”将简单地不予处理。

两个序列不需要具有相同的类型,元素类型也不必相同。为了展示这一点,我们使用了vector存储价格、用list存储权重。

16.5.4 泛化inner_product()

inner_product()可以像accumulate()那样泛化,但它需要两个额外参数:一个用于将累加器与新值组合起来(与accumulate()完全一样),另一个用于组合元素值对:

 

在16.6.3节中,我们将回到道琼斯的例子,给出一个更优雅的解决方案,其中就使用了这个泛化的inner_product()。

相关文章
|
1月前
|
机器学习/深度学习 算法 PyTorch
深度强化学习中SAC算法:数学原理、网络架构及其PyTorch实现
软演员-评论家算法(Soft Actor-Critic, SAC)是深度强化学习领域的重要进展,基于最大熵框架优化策略,在探索与利用之间实现动态平衡。SAC通过双Q网络设计和自适应温度参数,提升了训练稳定性和样本效率。本文详细解析了SAC的数学原理、网络架构及PyTorch实现,涵盖演员网络的动作采样与对数概率计算、评论家网络的Q值估计及其损失函数,并介绍了完整的SAC智能体实现流程。SAC在连续动作空间中表现出色,具有高样本效率和稳定的训练过程,适合实际应用场景。
209 7
深度强化学习中SAC算法:数学原理、网络架构及其PyTorch实现
|
1月前
|
负载均衡 算法 安全
探秘:基于 C++ 的局域网电脑控制软件自适应指令分发算法
在现代企业信息化架构中,局域网电脑控制软件如同“指挥官”,通过自适应指令分发算法动态调整指令发送节奏与数据量,确保不同性能的终端设备高效运行。基于C++语言,利用套接字实现稳定连接和线程同步管理,结合实时状态反馈,优化指令分发策略,提升整体管控效率,保障网络稳定,助力数字化办公。
52 19
|
2月前
|
算法 Java 数据库
理解CAS算法原理
CAS(Compare and Swap,比较并交换)是一种无锁算法,用于实现多线程环境下的原子操作。它通过比较内存中的值与预期值是否相同来决定是否进行更新。JDK 5引入了基于CAS的乐观锁机制,替代了传统的synchronized独占锁,提升了并发性能。然而,CAS存在ABA问题、循环时间长开销大和只能保证单个共享变量原子性等缺点。为解决这些问题,可以使用版本号机制、合并多个变量或引入pause指令优化CPU执行效率。CAS广泛应用于JDK的原子类中,如AtomicInteger.incrementAndGet(),利用底层Unsafe库实现高效的无锁自增操作。
理解CAS算法原理
|
1月前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
49 2
|
2月前
|
存储 算法 安全
基于红黑树的局域网上网行为控制C++ 算法解析
在当今网络环境中,局域网上网行为控制对企业和学校至关重要。本文探讨了一种基于红黑树数据结构的高效算法,用于管理用户的上网行为,如IP地址、上网时长、访问网站类别和流量使用情况。通过红黑树的自平衡特性,确保了高效的查找、插入和删除操作。文中提供了C++代码示例,展示了如何实现该算法,并强调其在网络管理中的应用价值。
|
1月前
|
存储 算法 安全
基于哈希表的文件共享平台 C++ 算法实现与分析
在数字化时代,文件共享平台不可或缺。本文探讨哈希表在文件共享中的应用,包括原理、优势及C++实现。哈希表通过键值对快速访问文件元数据(如文件名、大小、位置等),查找时间复杂度为O(1),显著提升查找速度和用户体验。代码示例展示了文件上传和搜索功能,实际应用中需解决哈希冲突、动态扩容和线程安全等问题,以优化性能。
|
2月前
|
机器学习/深度学习 人工智能 算法
深入解析图神经网络:Graph Transformer的算法基础与工程实践
Graph Transformer是一种结合了Transformer自注意力机制与图神经网络(GNNs)特点的神经网络模型,专为处理图结构数据而设计。它通过改进的数据表示方法、自注意力机制、拉普拉斯位置编码、消息传递与聚合机制等核心技术,实现了对图中节点间关系信息的高效处理及长程依赖关系的捕捉,显著提升了图相关任务的性能。本文详细解析了Graph Transformer的技术原理、实现细节及应用场景,并通过图书推荐系统的实例,展示了其在实际问题解决中的强大能力。
271 30
|
2月前
|
算法 安全 C++
用 C++ 算法控制员工上网的软件,关键逻辑是啥?来深度解读下
在企业信息化管理中,控制员工上网的软件成为保障网络秩序与提升办公效率的关键工具。该软件基于C++语言,融合红黑树、令牌桶和滑动窗口等算法,实现网址精准过滤、流量均衡分配及异常连接监测。通过高效的数据结构与算法设计,确保企业网络资源优化配置与安全防护升级,同时尊重员工权益,助力企业数字化发展。
65 4
|
2月前
|
存储 算法
深入解析PID控制算法:从理论到实践的完整指南
前言 大家好,今天我们介绍一下经典控制理论中的PID控制算法,并着重讲解该算法的编码实现,为实现后续的倒立摆样例内容做准备。 众所周知,掌握了 PID ,就相当于进入了控制工程的大门,也能为更高阶的控制理论学习打下基础。 在很多的自动化控制领域。都会遇到PID控制算法,这种算法具有很好的控制模式,可以让系统具有很好的鲁棒性。 基本介绍 PID 深入理解 (1)闭环控制系统:讲解 PID 之前,我们先解释什么是闭环控制系统。简单说就是一个有输入有输出的系统,输入能影响输出。一般情况下,人们也称输出为反馈,因此也叫闭环反馈控制系统。比如恒温水池,输入就是加热功率,输出就是水温度;比如冷库,
515 15
|
2月前
|
存储 人工智能 缓存
【AI系统】布局转换原理与算法
数据布局转换技术通过优化内存中数据的排布,提升程序执行效率,特别是对于缓存性能的影响显著。本文介绍了数据在内存中的排布方式,包括内存对齐、大小端存储等概念,并详细探讨了张量数据在内存中的排布,如行优先与列优先排布,以及在深度学习中常见的NCHW与NHWC两种数据布局方式。这些布局方式的选择直接影响到程序的性能,尤其是在GPU和CPU上的表现。此外,还讨论了连续与非连续张量的概念及其对性能的影响。
96 3