Matlab arrayfun 与 bsxfun——提高编程效率的利器!

news2024/11/13 15:25:15

许多人知道 MATLAB 向量化编程,少用 for 循环 可以提高代码运行效率,但关于代码紧凑化编程, arrayfun 与 bsxfun 两个重要函数却鲜有人能够用好,今天针对这两个函数举例说明其威力。

Matlab arrayfun

概述

arrayfun 是 Matlab 中的一个强大函数,它允许用户对数组中的每个元素应用一个指定的函数,并返回一个新的数组,该数组包含了函数对每个元素应用后的结果。这使得对数组进行逐元素操作变得非常灵活和方便,无需编写循环语句。

测试目的

本测试文档旨在展示 arrayfun 函数的多种巧妙用法,包括基本用法、匿名函数的应用、多维数组的处理以及与其他函数的结合使用,以全面理解其功能和效率。

  • 先看下面两个基本操作
A = 1:5;  
B = arrayfun(@(x) x^2, A);  
disp(B);


A = -5:5;  
B = arrayfun(@(x) x > 0, A);  
disp(B);

这两个操作中,arrayfun 提供了便利的逐元素操作方式,但在处理大型数组时,直接利用 Matlab 的内置数组向量化操作(如 +, -, .*, ./ 等)通常会有更好的性能。

  • 再看下面这个操作:
[J,I]=meshgrid(1:10);
al=arrayfun(@(ii,jj)  integral2(@(u,v)sin(u).*sqrt(v),0,ii,0,jj),I,J);

这段代码在MATLAB环境中执行了一个二维数值积分的计算,具体地,它计算了函数
f ( u , v ) = s i n ( u ) ⋅ v f(u,v)=sin(u)⋅ \sqrt{v} f(u,v)=sin(u)v
​ 在由点 (0, 0) 到点 (ii, jj) 形成的矩形区域上的积分,其中 (ii, jj) 遍历了一个由 meshgrid 函数生成的 10x10 网格的坐标点。让我们逐步解释这段代码的各个部分:

al=arrayfun(@(ii,jj)integral2(@(u,v)sin(u).*sqrt(v),0,ii,0,jj),I,J);
这行代码是代码的核心,它使用了 arrayfun 函数来对 I 和 J 数组中的每个 (ii, jj) 对执行一个函数。这个函数是一个匿名函数,它本身调用了 integral2 函数来执行二维数值积分。
integral2(@(u,v)sin(u).*sqrt(v),0,ii,0,jj) 调用 integral2 来计算函数 f(u, v) = \sin(u) \cdot \sqrt{v} 在矩形区域 [0, ii] x [0, jj] 上的积分。这里,@(u,v)sin(u).*sqrt(v) 定义了被积分的函数,而 0, ii, 0, jj 指定了积分的边界。
arrayfun 函数将这个 integral2 调用应用到 I 和 J 数组的每一个 (ii, jj) 对上,并将结果存储在数组 al 中。因此,al 是一个 10x10 的数组,其中 al(i,j) 存储了函数 f(u, v) 在矩形区域 [0, I(i,j)] x [0, J(i,j)] 上的积分值。

灵活性:这种方法允许用户轻松地对不同区域的函数进行积分,而无需手动编写多个积分调用。通过改变 meshgrid 函数的参数,可以轻松地调整积分的区域大小和形状。

显然这段代码是向量化编程难以执行的,而靠 arrayfun 函数两行搞定.

bsxfun(binary singleton expansion function )

概述

bsxfun是MATLAB中的一个函数,它允许对两个数组进行逐元素操作,同时自动扩展(或广播)较小的数组以匹配较大数组的维度。这使得在不需要显式循环的情况下执行复杂的数组操作成为可能,提高了代码的效率和简洁性。

测试案例

bsxfun 简单的函数操作见帮助文档,这里我们给一个高级的测试案例,展示了bsxfun的妙用:

  • 对两个二维数组每一行求差集
    MATLAB 目前只能对一维数组求差集,高维的话用 for loop 效率偏低。对于下面这种两个数组每一列只有一个不同元素的矩阵,对每一列求差集,完全可以不用 for loop:
%例如下面对 A,B 每一行求差集
% A = [1,2,3,4,5; 8,4,7,9,6];
% B = [2,3; 4,9];
% mask = all(bsxfun(@ne,A,permute(B,[1 3 2])),3);
% At = A.'; %//'
% out = reshape(At(mask.'),[],size(A,1)).';

% ---------------------------------------------------
%下面算例对两个矩阵每一列求差集   
B=[4   4   7   7   7   7   6   6   6   6   6   6
   3   9   9   5   9   8   2   9   4   4   9   8
   9   2   3   9   4   4   9   5   9   8   7   7
   1   1   1   1   3   9   1   1   2   9   5   9]';
A=[
   7   6   4   6   4   6   4   7   4   7   7   7
   9   2   3   9   3   4   9   5   9   8   5   8
   3   9   9   5   9   8   2   9   2   4   9   4
   1   1   1   1   1   9   1   1   1   9   1   9]';
mask = all(bsxfun(@ne,A,permute(B,[1 3 2])),3);
At = A.'; %//'
out = reshape(At(mask.'),[],size(A,1))
  • 再看下面这个:对比 bsxfun 与 repmat 运行效率:
n = 300;
k = 1; % Change to 100 for the second graph
a = ones(10,1);
rr = zeros(n,1);
bb = zeros(n,1);
ntt = 100;
tt = zeros(ntt,1);

for i = 1:n
    r = rand(1, i * k);
    
    % Timing bsxfun
    for it = 1:ntt
        tic;
        x = bsxfun(@plus, a, r);
        tt(it) = toc;
    end
    bb(i) = median(tt);
    
    % Timing repmat
    for it = 1:ntt
        tic;
        y = repmat(a, 1, i * k) + repmat(r, 10, 1);
        tt(it) = toc;
    end
    rr(i) = median(tt);
end

figure;
plot(1:n, bb, 'b', 'DisplayName', 'bsxfun');
hold on;
plot(1:n, rr, 'r', 'DisplayName', 'repmat');
legend('bsxfun','repmat')

运行时间对比结果:


可见对于大矩阵操作 bsxfun 效率更高!

So, 当你的矩阵规模比较大时,想想能否用 bsxfun 代替 repmat 吧!

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

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

相关文章

one-api 源码调试配置

本文主要介绍通过 VSCode 调试 one-api 源码。 一、环境配置 1.1 VSCode 和 one-api 安装 首先,确保已经安装了 VSCode(下载链接)和 one-api 源码(下载链接)已下载并安装了依赖 1.2 安装 Go 插件 在 VSCode 中,安装 Go 插件。 1.3 安装 dlv 调试包 可以通过下载源码…

EEtrade:现货黄金盈利计算方法

现货黄金交易作为一种极具吸引力的投资方式,其盈利计算涉及多个关键因素,投资者需深入理解这些因素,才能准确评估交易结果,并制定科学的投资策略。 一、现货黄金基本盈利计算: 利润公式: 利润 (收盘价 -…

docker部署mysql8.x版本,编写shell脚本自动部署安装mysql

docker部署mysql8.x版本&#xff0c;编写shell脚本自动部署安装mysql **1.**先自行安装好docker环境&#xff0c;docker的镜像注册中心最好是国内的&#xff0c;例如执行一下命令直接修改docker配置&#xff0c; cat <<EOF > /etc/docker/daemon.json {"regist…

LabVIEW学习-LabVIEW处理带分隔符的字符串从而获取数据

带分隔符的字符串很好处理&#xff0c;只需要使用"分隔符字符串至一维字符串数组"函数或者"一维字符串数组至分隔符字符串"函数就可以很轻松地处理带分隔符地字符串。 这两个函数所在的位置为&#xff1a; 函数选板->字符串->附加字符串函数->分…

在STM32嵌入式中C/C++语言对栈空间的使用

像STM32这样的微控制器在进入main函数之前需要对栈进行初始化。可以说栈是C语言运行时的必要条件。我们知道栈实际上是一块内存空间&#xff0c;那么这块空间都用来存储什么呢&#xff1f;有什么办法能够优化栈空间的使用&#xff1f; 栈空间保存的内容 栈是一个先入后出的数据…

学术研讨 | 区块链网络体系结构研讨会顺利召开

添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 近日&#xff0c;国家区块链技术创新中心组织了“区块链网络体系结构研讨会”&#xff0c;会议面向跨域交互多、计算规模大、数据管理复杂、性能与扩展性要求高等特征的区块链网络的体系结构展开交流研讨&…

ShareDB:构建实时应用从未如此简单

项目介绍 ShareDB 是一个支持多用户实时协作的全栈库&#xff0c;适用于构建各种需要同步数据更新的在线应用&#xff0c;如在线文档编辑器、实时仪表板和多玩家游戏等。 它提供了一套全面的实时同步和多用户协作解决方案&#xff0c;具备异步最终一致性、实时查询订阅、数据库…

Win11 操作(四)g502鼠标连接电脑不亮灯无反应

罗技鼠标连接电脑不亮灯无反应 前言 罗技技术&#x1f4a9;中&#x1f4a9;&#xff0c;贴吧技术神中神&#xff01; 最近买了一个g502&#xff0c;结果买回来直接插上电脑连灯都不亮&#xff0c;问了一下客服。客服简单的让我换接口&#xff0c;又是下载ghub之类的&#xf…

ESP8266用AT指令实现连接MQTT

1准备工作 硬件&#xff08;ESP8266&#xff09;连接电脑 硬件已经烧入了MQTT透传固件 2实现连接 2-1&#xff08;进入AT模式&#xff09; 打开串口助手发送如下指令 AT 2-2&#xff08;复位&#xff09; ATRST 2-3&#xff08;开启DHCP&#xff0c;自动获取IP&#x…

SpringBoot+Vue(3)Excel的在线预览

一、思路 在Spring Boot和Vue.js的组合中实现Excel文件的在线预览功能&#xff0c;通常涉及到几个关键步骤&#xff1a;文件上传、文件存储、文件读取、以及通过前端展示Excel内容。由于Excel文件本身不是直接可以在网页上渲染的格式&#xff0c;我们通常需要将Excel文件转换为…

vue3创建vite项目

一、创建vue3 vite项目&#xff1a; 命令行创建&#xff1a;npm create vitelatest vue3-tdly-demo -- --template vue (1)先进入项目文件夹&#xff0c;cd vue3-tdly-demo (2)之后执行&#xff0c; npm install (3)最后运行&#xff0c;npm run dev 将main.js文件内容改成…

ML.NET:一个.NET开源、免费、跨平台的机器学习框架

前言 今天大姚给大家分享一个.NET开源、免费、跨平台&#xff08;支持Windows、Linux、macOS多个操作系统&#xff09;的机器学习框架&#xff1a;ML.NET。并且本文将会带你快速使用ML.NET训练一个属于自己的图像分类模型&#xff0c;对图像进行分类。 ML.NET框架介绍 ML.NET…

计算机网络之网络基础(含图解和知识点思维导图通俗易懂)

绪论​ “一个人在科学探索的道路上&#xff0c;走过弯路&#xff0c;犯过错误&#xff0c;并不是坏事&#xff0c;更不是什么耻辱&#xff0c;要在实践中勇于承认和改正错误。——爱因斯坦”。本章将是网络的第一章&#xff0c;计算机网络是我们计算机行业必须了解并掌握的知识…

Linux中的fopen,fclose,fread,fwrite,fseek相关函数的知识点

这几个函数都是标准的c库函数&#xff0c;在man 2中查找不到&#xff0c;所以我们可以利用man 手册直接查找 对应的open,close,write,fread都是Linux系统内核调用 可移植性&#xff1a;fopen 强过于 open ... fopen 在用户态是缓存的 open 在用户态是没有缓存的 fopen函数 f…

TCP粘包问题详解和解决方案【C语言】

1.什么是TCP粘包 TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是一种面向连接的、可靠的、基于字节流的传输协议&#xff0c;它保证了数据的可靠性和顺序性。然而&#xff0c;由于TCP是基于字节流而不是消息的&#xff0c;因此在传输过…

javaEE-01-tomcat

文章目录 javaWebTomcat启动 Tomcat 服务器测试服务器是否成功停止tomcat服务器修改服务器的端口号 Idea整合tomcat服务器 javaWeb 所有通过 Java 语言编写可以通过浏览器访问的程序的总称,是基于请求和响应来开发的。 请求: 客户端给服务器发送数据(Request)响应: 服务器给客…

LINUX环境下使用yum安装JDK1.8并配置环境变量

LINUX环境下使用yum安装JDK1.8并配置环境变量 1.查看CentOS自带JDK是否已安装 yum list installed |grep java2.批量卸载JDK rpm -qa | grep java | xargs rpm -e --nodeps3.直接yum安装1.8.0版本openjdk(其他版本请自行修改版本号) yum install java-1.8.0-openjdk* -y4.默…

4 Go语言的操作符

本专栏将从基础开始&#xff0c;循序渐进&#xff0c;由浅入深讲解Go语言&#xff0c;希望大家都能够从中有所收获&#xff0c;也请大家多多支持。 查看相关资料与知识库 专栏地址:Go专栏 如果文章知识点有错误的地方&#xff0c;请指正&#xff01;大家一起学习&#xff0c;…

智慧园区整体一站式解决方案(PPT原件完整版)

软件全套资料部分文档清单&#xff1a; 工作安排任务书&#xff0c;可行性分析报告&#xff0c;立项申请审批表&#xff0c;产品需求规格说明书&#xff0c;需求调研计划&#xff0c;用户需求调查单&#xff0c;用户需求说明书&#xff0c;概要设计说明书&#xff0c;技术解决方…

SQL labs-SQL注入(四,sqlmap对于post传参方式的注入)

本文仅作为学习参考使用&#xff0c;本文作者对任何使用本文进行渗透攻击破坏不负任何责任。 序言&#xff1a;本文主要讲解基于SQL labs靶场&#xff0c;sqlmap工具进行的post传参方式的SQL注入。 传参方式有两类&#xff0c;一类是直接在url栏内进行url编码后进行的传参&am…