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()。

时间: 2024-08-31 13:04:15

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

c++-关于《C++程序设计原理与实践》第3章例子的一个问题

问题描述 关于<C++程序设计原理与实践>第3章例子的一个问题 本人菜鸟,现正在学习C++.<C++程序设计原理与实践>第3章有一个例子,代码如下: #include #include #include #include #include using namespace std; inline void keep_window_open(){ char ch; cin >> ch; } int main() //C++ Programs start by executi

源代码-C++程序设计原理与实践

问题描述 C++程序设计原理与实践 #include "std_lib_facilities.h" int main() { cout<<"Hello,world!n"; return 0; } 我下了源代码,放到那里才能猜VC98编译时不出错?最好详细点,带有图解 解决方案 ...大哥,都什么年代了还用98

《 C++程序设计:原理与实践(进阶篇.》导读

本节书摘来自华章出版社< C++程序设计:原理与实践(进阶篇)>一书中作者[美] 本贾尼·斯特劳斯特鲁普(Bjarne Stroustrup) 著 刘晓光 李忠伟 王刚 译     前 言 Programming: Principles and Practice Using C++, Second Edition 该死的鱼雷!全速前进. --Admiral Farragut 程序设计是这样一门艺术,它将问题求解方案描述成计算机可以执行的形式.程序设计中很多工作都花费在寻找求解方案以及对其求精上

100分求java语言程序设计进阶篇pdf

问题描述 求java语言程序设计进阶篇pdf 解决方案 解决方案二:同求啊!!!解决方案三:这个网上是没有的,我也在网上找过,我建议你去网上找java核心技术<上下卷>pdf这本书写的也是不错的,,这个网上有电子书的,,这两本书配合着java编程思想,相当的不错的解决方案四:真正的进阶是需要项目练习的,纸上得来终觉浅解决方案五:引用2楼xinzailiulei的回复: 这个网上是没有的,我也在网上找过,我建议你去网上找java核心技术<上下卷>pdf这本书写的也是不错的,,这个网上

学一点 mysql 双机异地热备份----快速理解mysql主从,主主备份原理及实践

原文 学一点 mysql 双机异地热备份----快速理解mysql主从,主主备份原理及实践 感谢大家在上一篇 学一点Git--20分钟git快速上手 里的踊跃发言.这里再次分享干货, 简单介绍mysql双机,多机异地热备简单原理实战. 双机热备的概念简单说一下,就是要保持两个数据库的状态自动同步.对任何一个数据库的操作都自动应用到另外一个数据库,始终保持两个数据库数据一 致. 这样做的好处多. 1. 可以做灾备,其中一个坏了可以切换到另一个. 2. 可以做负载均衡,可以将请求分摊到其中任何一台上

Node.js Stream - 进阶篇

上篇(基础篇)主要介绍了Stream的基本概念和用法,本篇将深入剖析背后工作原理,重点是如何实现流式数据处理和 back pressure 机制. 目录 本篇介绍 stream 是如何实现流式数据处理的. 数据生产和消耗的媒介 为什么使用流取数据 下面是一个读取文件内容的例子: const fs = require('fs') fs.readFile(file, function (err, body) { console.log(body) console.log(body.toString(

SQL Server调优系列进阶篇(如何索引调优)

原文:SQL Server调优系列进阶篇(如何索引调优) 前言 上一篇我们分析了数据库中的统计信息的作用,我们已经了解了数据库如何通过统计信息来掌控数据库中各个表的内容分布.不清楚的童鞋可以点击参考. 作为调优系列的文章,数据库的索引肯定是不能少的了,所以本篇我们就开始分析这块内容,关于索引的基础知识就不打算深入分析了,网上一搜一片片的,本篇更侧重的是一些实战项内容展示,希望通过本篇文章各位看官能在真正的场景中找到合适的解决方法足以. 对于索引的使用,我希望的是遇到问题找到合适的解决方法就可以,

推荐系统——从原理到实践,还有福利赠送!

之前流水账似的介绍过一篇机器学习入门的文章,大致介绍了如何学习以及机器学习的入门方法并提供了一些博主自己整理的比较有用的资源.这篇就尽量以白话解释并介绍机器学习在推荐系统中的实践以及遇到的问题... 也许很多点在行家的眼里都是小菜一碟,但是对于刚刚接触机器学习来说,还有很多未知等待挑战. 所以读者可以把本篇当做是机器学习的玩具即可,如果文中有任何问题,还请不吝指教. 本篇将会以下面的步骤描述机器学习是如何在实践中应用的: 1 什么是推荐系统? 2 机器学习的作用 3 机器学习是如何使用的? 4

SQL Server调优系列进阶篇(如何维护数据库索引)

原文:SQL Server调优系列进阶篇(如何维护数据库索引) 前言 上一篇我们研究了如何利用索引在数据库里面调优,简要的介绍了索引的原理,更重要的分析了如何选择索引以及索引的利弊项,有兴趣的可以点击查看. 本篇延续上一篇的内容,继续分析索引这块,侧重索引项的日常维护以及一些注意事项等. 闲言少叙,进入本篇的主题. 技术准备 数据库版本为SQL Server2012,前几篇文章用的是SQL Server2008RT,内容区别不大,利用微软的以前的案例库(Northwind)进行分析,部分内容也会

《C++程序设计入门同步实践宝典 》可以下载了

<C++程序设计入门同步实践宝典>可以告一段落了.这是假期计划之外的事情,不小心又花了近二十天的时间,其他计划中的事情得一一落实了.将此版定为0.5版,以后还会有不小的改动. 下载地址:http://download.csdn.net/detail/sxhelijian/4482514 下载需要资源分5分,以对自己辛苦一番有所表示.常在CSDN泡的同学,也应该分享些你的原创挣点积分了.缺少积分的穷孩子,也可以给我留言,提供Email寄过去. 发个封皮: 有人提出上目录,好主意: 完工后写的前言