C++11标准模板(STL)- 算法(std::inner_product)

news2024/10/6 2:24:49
定义于头文件 <algorithm>

算法库提供大量用途的函数(例如查找、排序、计数、操作),它们在元素范围上操作。注意范围定义为 [first, last) ,其中 last 指代要查询或修改的最后元素的后一个元素。

计算两个范围的元素的内积

std::inner_product
template< class InputIt1, class InputIt2, class T >

T inner_product( InputIt1 first1, InputIt1 last1,

                 InputIt2 first2, T init );
(1)
template<class InputIt1, class InputIt2, class T,

         class BinaryOperation1, class BinaryOperation2>
T inner_product( InputIt1 first1, InputIt1 last1,
                 InputIt2 first2, T init,
                 BinaryOperation1 op1,

                 BinaryOperation2 op2 );
(2)

 

计算内积(即积之和)或在范围 [first1, last1) 和始于 first2 的范围上进行有序映射/规约操作。

1) 以初值 init 初始化积累器 acc ,然后

以表达式 acc = acc + *first1 * *first2 修改它,再以表达式 acc = acc + *(first1+1) * *(first2+1) 修改它,以此类推

(C++20 前)

以表达式 acc = std::move(acc) + *first1 * *first2 修改它,再以表达式 acc = std::move(acc) + *(first1+1) * *(first2+1) 修改它,以此类推

(C++20 起)

直至抵达 last1 。对于 + 与 * 的内建含义,此算法计算二个范围的内积。2) 以初值 init 初始化积累器 acc ,然后

以表达式 acc = op1(acc, op2(*first1, *first2)) 修改它,再以表达式 acc = op1(acc, op2(*(first1+1), *(first2+1))) 修改它,以此类推

(C++20 前)

以表达式 acc = op1(std::move(acc), op2(*first1, *first2)) 修改它,再以表达式 acc = op1(std::move(acc), op2(*(first1+1), *(first2+1))) 修改它,以此类推

(C++20 起)

直至抵达 last1

op1op2 必须无副效应。

(C++11 前)

op1op2 必须不非法化所涉及范围的任何迭代器,含尾迭代器或修改该范围的任何元素。

(C++11 起)

参数

first1, last1-元素范围
first2-第二个元素范围的起始
init-积的和的初值
op1-被使用的二元函数对象。此“和”函数接收 op2 所返回的值和当前积累器的值,并产生存储于积累器的新值。

该函数的签名应当等价于:

 Ret fun(const Type1 &a, const Type2 &b);

签名中并不需要有 const &。
类型 Type1 与 Type2 必须使得 T 与 Type3 类型的对象各能隐式转换成 Type1 与 Type2 。 类型 Ret 必须使得 T 类型对象能被赋 Ret 类型值。 ​

op2-被使用的二元函数对象。此“积”函数从每个范围接收一个值并产生新值。

该函数的签名应当等价于:

 Ret fun(const Type1 &a, const Type2 &b);

签名中并不需要有 const &。
类型 Type1 与 Type2 必须使得 InputIt1 与 InputIt2 类型的对象在解引用后分别能隐式转换到 Type1 与 Type2 。 类型 Ret 必须使得 Type3 类型对象能被赋 Ret 类型值。 ​

类型要求
- InputIt1, InputIt2 必须满足遗留输入迭代器 (LegacyInputIterator) 的要求。
- ForwardIt1, ForwardIt2 必须满足遗留向前迭代器 (LegacyForwardIterator) 的要求。
- T 必须满足可复制赋值 (CopyAssignable) 和 可复制构造 (CopyConstructible) 的要求。

返回值

上述 acc 的最终值。

可能的实现

版本一

template<class InputIt1, class InputIt2, class T>
T inner_product(InputIt1 first1, InputIt1 last1,
                InputIt2 first2, T init)
{
    while (first1 != last1) {
         init = std::move(init) + *first1 * *first2; // C++20 起有 std::move
         ++first1;
         ++first2;
    }
    return init;
}

版本二

template<class InputIt1, class InputIt2,
         class T,
         class BinaryOperation1, class BinaryOperation2>
T inner_product(InputIt1 first1, InputIt1 last1,
                InputIt2 first2, T init,
                BinaryOperation1 op1,
                BinaryOperation2 op2)
{
    while (first1 != last1) {
         init = op1(std::move(init), op2(*first1, *first2)); // C++20 起有 std::move
         ++first1;
         ++first2;
    }
    return init;
}

注意

此算法的可并行版本 std::transform_reduce 要求 op1op2 可交换并可结合,但 std::inner_product 不作这种要求,且始终以给定顺序进行操作。

调用示例

#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
#include <list>
#include <iterator>
#include <time.h>

using namespace std;

struct Cell
{
    int x;
    int y;

    Cell &operator +=(const Cell &cell)
    {
        x += cell.x;
        y += cell.y;
        return *this;
    }

    Cell &operator +(const Cell &cell)
    {
        x += cell.x;
        y += cell.y;
        return *this;
    }

    Cell &operator *(const Cell &cell)
    {
        x *= cell.x;
        y *= cell.y;
        return *this;
    }

    Cell &operator ++()
    {
        x += 1;
        y += 1;
        return *this;
    }

    bool operator <(const Cell &cell) const
    {
        if (x == cell.x)
        {
            return y < cell.y;
        }
        else
        {
            return x < cell.x;
        }
    }

    bool operator ==(const Cell &cell) const
    {
        return x == cell.x && y == cell.y;
    }
};

std::ostream &operator<<(std::ostream &os, const Cell &cell)
{
    os << "{" << cell.x << "," << cell.y << "}";
    return os;
}

int main()
{
    std::mt19937 g{std::random_device{}()};

    srand((unsigned)time(NULL));;

    std::cout << std::boolalpha;

    std::function<Cell()> generate = []()
    {
        int n = std::rand() % 10;
        Cell cell{n, n};
        return cell;
    };

    // 初始化lCells1
    std::list<vector<Cell>> lCells1(3, vector<Cell>(5));
    //用从起始值开始连续递增的值填充一个范围
    for (vector<Cell> &vCells : lCells1)
    {
        std::generate(vCells.begin(), vCells.end(), generate);
    }

    // 初始化lCells1
    std::list<vector<Cell>> lCells2(3, vector<Cell>(5));
    //用从起始值开始连续递增的值填充一个范围
    for (vector<Cell> &vCells : lCells2)
    {
        std::generate(vCells.begin(), vCells.end(), generate);
    }

    size_t index = 0;
    std::list<vector<Cell>>::iterator it1 = lCells1.begin();
    std::list<vector<Cell>>::iterator it2 = lCells2.begin();
    for (; it1 != lCells1.end() && it2 != lCells2.end(); it1++, it2++)
    {
        std::cout << "lCells1 " << index << " ";
        std::copy((*it1).begin(), (*it1).end(), std::ostream_iterator<Cell>(std::cout, " "));
        std::cout << std::endl;

        std::cout << "lCells1 " << index << " ";
        std::copy((*it2).begin(), (*it2).end(), std::ostream_iterator<Cell>(std::cout, " "));
        std::cout << std::endl;

        auto inner_product = std::inner_product((*it1).begin(), (*it1).end(), (*it2).begin(), Cell{0, 0});
        std::cout << "inner_product: " << inner_product << std::endl;
        std::cout << std::endl;
        index++;
    }

    std::cout << std::endl;
    std::cout << std::endl;
    std::cout << std::endl;

    auto opt1 = [](const Cell & a, const Cell & b)
    {
        Cell cell{a.x + b.x, a.y + b.y};
        return cell;
    };

    auto opt2 = [](const Cell & a, const Cell & b)
    {
        Cell cell{a.x * b.x, a.y * b.y};
        return cell;
    };

    // 初始化lCells3
    std::list<vector<Cell>> lCells3(3, vector<Cell>(5));
    //用从起始值开始连续递增的值填充一个范围
    for (vector<Cell> &vCells : lCells3)
    {
        std::generate(vCells.begin(), vCells.end(), generate);
    }

    // 初始化lCells4
    std::list<vector<Cell>> lCells4(3, vector<Cell>(5));
    //用从起始值开始连续递增的值填充一个范围
    for (vector<Cell> &vCells : lCells4)
    {
        std::generate(vCells.begin(), vCells.end(), generate);
    }

    index = 0;
    std::list<vector<Cell>>::iterator it3 = lCells3.begin();
    std::list<vector<Cell>>::iterator it4 = lCells4.begin();
    for (; it3 != lCells3.end() && it4 != lCells4.end(); it3++, it4++)
    {
        std::cout << "lCells1 " << index << " ";
        std::copy((*it3).begin(), (*it3).end(), std::ostream_iterator<Cell>(std::cout, " "));
        std::cout << std::endl;

        std::cout << "lCells1 " << index << " ";
        std::copy((*it4).begin(), (*it4).end(), std::ostream_iterator<Cell>(std::cout, " "));
        std::cout << std::endl;

        auto inner_product = std::inner_product((*it3).begin(), (*it3).end(), (*it4).begin(),
                                                Cell{0, 0}, opt1, opt2);
        std::cout << "inner_product: " << inner_product << std::endl;
        std::cout << std::endl;
        index++;
    }

    return 0;
}

输出

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

十七、Docker Compose容器编排第二篇

在上一篇中我们讲解了容器编排是什么、能干什么、怎么安装、使用步骤&#xff0c;如果没有看的大家可以先看下&#xff1a;https://blog.csdn.net/u011837804/article/details/128335166&#xff0c;然后继续看这一篇&#xff0c;好了&#xff0c;我们继续。 1、Docker Compons…

gl-Camera

我的服务原文访问&#xff1a;Camera 1.创建摄像机的坐标系&#xff0c;&#xff08;创建原理&#xff0c;两条直线求其法向量&#xff09; Z轴:在世界坐标中指向摄像机的向量&#xff08;D&#xff09; X轴&#xff1a;随便找一个向上量和Z向量求出的法向量就是X轴&#xf…

PostgreSQL数据库TableAM——Table scan callbacks

TableAM Table scan TableAM提供了如下4个接口用于实现表数据的扫描功能。scan_begin函数的形参nkeys不为零&#xff0c;则扫描结果需要根据scan keys先进行过滤&#xff1b;pscan如果不为null&#xff0c;说明该结构体已经由parallelscan_initialize初始化过了(仅仅在table_b…

初识Docker:(5)Docker自定义镜像

初识Docker&#xff1a;&#xff08;5&#xff09;Docker自定义镜像镜像结构Dockerfile语法什么是Dockerfile构建Java项目案例1&#xff1a;基于ubuntu镜像构建一个新镜像&#xff0c;运行一个java项目案例2&#xff1a;基于java:8-alpine镜像&#xff0c;将一个java项目构建为…

Java+JSP机房课表管理系统(含源码+论文+答辩PPT等)

项目功能简介: 该项目采用技术CSSJavaScriptMySQLServlet、MySQL数据库、项目含有源码、配套开发软件、软件安装教程、项目发布教程等 项目功能介绍&#xff1a; 系统管理&#xff1a;包含用户的注册&#xff0c;管理&#xff0c;信息修改 课程管理&#xff1a;包含课程录入、维…

IT大侦“碳”:VxRail的可持续法宝

环境Environmental      社会责任Social Responsibility      企业治理Corporate Governance      随着碳达峰、碳中和的逐步推进,越来越多的“大厂”或各行业的明星企业都开始重视自己的ESG报告,已然成为了商界新风尚。      可持续发展战略也与前沿技术密切相…

matlab神经网络求解最优化,matlab神经网络训练数据

1、神经网络的准确率是怎么计算的&#xff1f; 其实神经网络的准确率的标准是自己定义的。 我把你的例子赋予某种意义讲解&#xff1a; 1&#xff0c;期望输出[1 0 0 1]&#xff0c;每个元素代表一个属性是否存在。像着4个元素分别表示&#xff1a;是否肺炎&#xff0c;是否肝…

哈希知识点

目录对比map/set1. unordered系列关联式容器1.1 unordered_map2. 底层结构2.1 哈希概念2.2 哈希冲突2.3 哈希函数2.4 哈希冲突解决2.4.1 闭散列线性探测和二次探测扩容&#xff08;负载因子&#xff09;闭散列实现的hash2.4.2 开散列概念开散列思考实现模拟实现模板参数列表的改…

Java项目:springboot农业物资管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 农业物资管理系统&#xff0c;管理员可以对角色进行配置&#xff0c;分配用户角色&#xff1b; 主要功能包含&#xff1a;登录、注册、修改密码…

并查集解决重复员工问题

简介 工作一年多了&#xff0c;天天CRUD&#xff0c;终于以前学习的算法排上用场了。 背景 我们的系统在用户注册时没有校验身份id&#xff08;身份证&#xff09;和电话号码的唯一&#xff0c;可能使用相同的身份id或者电话号码创建多个账号&#xff0c;导致有些人开多个账…

面试者推荐 |【Redis面试专题】「常见问答系列」透析Redis常见技术相关的问题1~10题(进阶)

&#x1f4da; 前提回顾 首先如果没有阅读【面试者推荐 |【Redis面试专题】「常见问答系列」透析Redis常见技术相关的问题1~10题&#xff08;基础&#xff09; 】&#xff0c;简易先去看看基础10题&#xff0c;因为循序渐进才是正道&#xff0c;哈哈。 &#x1f4da; 1. Redis…

WebRTC源码之RTCPReceiver源码分析

WebRTC源码之RTCPReceiver源码分析 WebRTC源码之RTCPReceiver源码分析WebRTC源码之RTCPReceiver源码分析前言一、 RTCP接受数据的流程的堆栈信息的1、网络io 线程读取数据2、 线程切换的代码3、 线程切换 gcc二、 RTCPReceiver::IncomingPacket方法读取RTCP数据的格式1、 Parse…

【PyTorch深度学习项目实战100例】—— 基于DPCNN实现电商情感分析任务 | 第79例

前言 大家好,我是阿光。 本专栏整理了《PyTorch深度学习项目实战100例》,内包含了各种不同的深度学习项目,包含项目原理以及源码,每一个项目实例都附带有完整的代码+数据集。 正在更新中~ ✨ 🚨 我的项目环境: 平台:Windows10语言环境:python3.7编译器:PyCharmPy…

随机种子 3407 is all you need

文 | 天于刀刀你最常用的随机种子是哪个&#xff1f;在刀刀的团队里&#xff0c;关于随机种子的设置主要分化为两派~玄学派&#xff0c;可能设置为自己的纪念日&#xff0c;又或者是星座预测中的本月幸运数字&#xff1b;以及&#xff0c;自然派&#xff0c;随机种子是啥其实无…

Java项目:springboot健身房管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 本项目为后台管理系统&#xff1b; 主要功能如下&#xff1a; 管理员登录模块 会员管理模块 教练管理模块 课程管理模块 器材管理模块 物品遗失…

一些常见的移动端适配方案,你了解吗?

前言 移动端设备的尺寸很多&#xff0c;而 UI 设计稿一般只会基于一个尺寸&#xff08;一般是 375px 或 750px &#xff09;进行设计。 目前移动端适配方案有多种&#xff0c;本文将介绍一些具有代表性的适配方案。 媒体查询 media CSS3 中的媒体查询属性 media 分别为不同…

量子计算(十七):量子计算机硬件

文章目录 量子计算机硬件 一、量子芯片支持系统 二、量子计算机控制系统 量子计算机硬件 量子计算机的核心——量子芯片&#xff0c;具有多种不同的呈现形式。绝大多数量子芯片&#xff0c;名副其实地&#xff0c;是一块芯片&#xff0c;由集成在基片表面的电路结构构建出包…

关于 Camera 开始 Tuning 时的一些注意事项

1、问题背景&#xff1a; 最近有调试一个体感游戏机上带 Camera 的项目&#xff0c;原定搭配 ov13855 这颗 sensor, 但由于各种各样的问题&#xff0c;导致做了很多无用功&#xff0c;且各种延期。 本文主要总结下此次项目遇到的问题&#xff0c;及产品开始 tuning 时的一些注意…

【折腾服务器 4】ESXi 中 Ubuntu 安装 NPS 客户端 ( NPC )

Catch Up 书接上回&#xff0c;上一章中&#xff0c;群晖已经能定期给 Windows 物理机服务器做备份了&#xff0c;但是依然无法从外网访问服务器上的内容&#xff0c;本篇讲述如何在 Ubuntu 中安装 NPS 客户端&#xff0c;也就是所谓的 NPC ( Client )。 Chapter 1 准备一个 …

C#语言实例源码系列-实现FTP下载文件

专栏分享点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册 &#x1f449;关于作者 众所周知&#xff0c;人生是一个漫长的流程&#xff0c;不断克服困难&#xff0c;不断反思前进的过程。在这个过程中…