玖叶教程网

前端编程开发入门

Matlab 中编程技法分享(matlab编程入门教程)

“时问桫椤”公众号,一个不太正式的学术加油站,专为本科生到研究生的你提供“非正式”援助。当你感到迷茫、痛苦,或是被学术大山压得喘不过气时,我们就是你的“学术救生圈”。我们用研究生们的血泪经验,帮你快速适应研究生生活,揭开科研的神秘面纱。祝你一路顺风,科研路上不翻车!

非常感谢各位的点赞,关注和转发,你们的点赞和关注是我更新的动力[1]

技法分享

  1. 尽量避免使用循环结构

MATLAB变量的基本类型是矩阵,当对矩阵的每个元素循环处理时,运算速度很慢。因此编程时应尽量把数组和矩阵看作一个整体来进行编程,而不是像其他的程序设计语言那样,使用循环结构对矩阵的元素循环进行处理。

利用MATLAB提供的用于矢量化操作的函数,把循环矢量化,这样既可以提高编程效率,也可以提高程序的执行效率。

下面给出一个循环的例子:

i=0;

for n =0:0.1:100

i=i+1;

y(i)=cos(n)

end

上述程序段把数组中的每个元素都进行函数值计算,这样会耗费大量的运算时间,我们可以把数组看作一个整体来处理,计算函数值,可以修改这个程序段如下。

n = 0:0.1:100;

y = cos(n)

通过使用MATLAB专门提供的测试程序运行时间的函数,可以发现,把数组看作一个整体,进行操作后,执行效率提高约300倍。

另外,在必须使用多重循环的情况下,建议在循环的外环执行循环次数少的,内环执行循环次数多的,这样也可以显著提高程序执行速度。

  1. 在使用数组或矩阵之前先定义维数

MATLAB中的变量在使用之前不需要明确地定义和指定维数。

但当未预定义数组或矩阵的维数时,当需赋值的元素下标超出现有的维数时,MATLAB 就为该数组或矩阵扩维一次,这样就会大大降低程序的执行效率。

因此,在使用数组或矩阵之前,预定义维数可以提高程序的执行效率。

  1. 对矩阵元素使用下标或者索引操作

在MATLAB中,矩阵元素的引用可用两个下标来表示。例如:

A(i,j) 表示矩阵的第i行第j列的元素;

A(1:k,j)表示矩阵A的第j列的前k个元素;

A(:,j) 表示矩阵的第j列的所有元素。

求矩阵A的第j列元素的平均值的表达式为mean(A(:,j))。
  1. 尽量多使用函数文件少使用脚本文件

因为每次调用MATLAB的脚本文件都需要将不必要的中间变量加载到内存中,每执行一次,就加载一次。

函数在调用时被编译成了伪代码,只需要加载到内存一次。当多次调用同一个函数时会运行快一些。

因此尽量多使用函数文件而少使用脚本文件,也是提高执行效率的一种方法。

  1. 在必须使用循环时,可以考虑转换为C-MEX

当必须使用耗时的循环时,可以考虑将循环体中的语句转换为C-MEX。

C-MEX是将M文件通过MATLAB 的编译器转换为可执行文件,是按照 MEX 技术要求的格式编写相应的程序,通过编译连接,生成扩展名为.dll的动态链接库文件,可以在MATLAB环境下直接执行。

这样,循环体中的语句在执行时不必每次都解释(interpret)。一般来说,C-MEX 文件的执行速度是相同功能的M文件执行速率的20~40倍。

编写C-MEX不同于M文件,需要了解MATLAB C-MEX规范。幸运的是MATLAB提供了将M文件转换为C-MEX的工具。

  1. 内存优化

MATLAB在进行复杂的运算时需要占用大量的内存。

合理使用内存和提高内存的使用效率,可以加快运行速度,减少系统资源的占用。

  1. 内存管理函数和命令

● Clear variablename:从内存中删除名称为variablename的变量。

● Clear all:从内存中删除所有的变量。

● Save:将指令的变量存入磁盘。

● Load:将save命令存入的变量载入内存。

● Quit:退出MATLAB,并释放所有分配的内存。

● Pack:把内存中的变量存入磁盘,再用内存中的连续空间载回这些变量。考虑到执行效率问题,不能在循环中使用。

  1. 节约内存的方法

● 避免生成大的中间变量,并删除不再需要的临时变量。

● 当使用大的矩阵变量时,预先指定维数并分配好内存,避免每次临时扩充维数。

● 当程序需要生成大量变量数据时,可以考虑定期将变量写到磁盘,然后清除这些变量。当需要这些变量时,再重新从磁盘加载。

● 当矩阵中数据极少时,将全矩阵转换为稀疏矩阵。

函数式编程

函数式编程是一种编程范式,它强调使用纯函数、不可变数据和高阶函数来构建应用程序。在函数式编程中,我们避免使用副作用和可变状态,而是通过函数来处理数据。以下是一些常见的函数式编程技巧和方法,用于替代传统的循环和条件判断:

  1. 使用map替代for循环map函数接受一个函数和一个数组,返回一个新数组,其中的元素是原始数组元素应用给定函数的结果。 // 传统for循环
    let numbers = [1, 2, 3, 4];
    let squaredNumbers = [];
    for (let i = 0; i < numbers.length; i++) {
    squaredNumbers.push(numbers[i] * numbers[i]);
    }

    // 函数式编程中的map
    let squaredNumbersFunctional = numbers.map(x => x * x);
  2. 使用reduce进行累加或聚合操作reduce函数接受一个累加器函数和一个初始值,将数组中的所有元素减少到单个值。 // 传统for循环累加
    let sum = 0;
    for (let i = 0; i < numbers.length; i++) {
    sum += numbers[i];
    }

    // 函数式编程中的reduce
    let sumFunctional = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
  3. 使用filter进行条件筛选filter函数接受一个测试函数和一个数组,返回所有使得测试函数返回true的元素组成的新数组。 // 传统for循环筛选
    let evenNumbers = [];
    for (let i = 0; i < numbers.length; i++) {
    if (numbers[i] % 2 === 0) {
    evenNumbers.push(numbers[i]);
    }
    }

    // 函数式编程中的filter
    let evenNumbersFunctional = numbers.filter(x => x % 2 === 0);
  4. 使用find或findIndex寻找满足条件的第一个元素find返回数组中满足提供的测试函数的第一个元素的值。如果没有这样的元素,则返回undefined // 传统for循环查找
    let firstEvenNumber;
    for (let i = 0; i < numbers.length; i++) {
    if (numbers[i] % 2 === 0) {
    firstEvenNumber = numbers[i];
    break;
    }
    }

    // 函数式编程中的find
    let firstEvenNumberFunctional = numbers.find(x => x % 2 === 0);
  5. 使用some或every进行条件检查some测试数组中是否至少有一个元素满足提供的测试函数。every测试数组中的所有元素是否都满足提供的测试函数。 // 传统if else检查
    if (numbers.some(x => x > 10)) {
    console.log("At least one number is greater than 10.");
    }

    // 函数式编程中的some
    numbers.some(x => x > 10) && console.log("At least one number is greater than 10.");
  6. 使用compose和pipe进行函数组合composepipe允许你将多个函数组合成一个函数,从而减少嵌套和提高可读性。 // 函数组合
    const squareAndAddOne = R.pipe(
    R.map(R.add(1)),
    R.map(R.multiply(2))
    );

    squareAndAddOne([1, 2, 3]); // [4, 6, 8]
  7. 使用switch替代多个if else分支: 虽然switch不是函数式编程特有的,但在某些情况下,它可以替代多个if else分支,使代码更加清晰。 // 传统if else分支
    if (condition) {
    // do something
    } else if (anotherCondition) {
    // do something else
    } else {
    // default case
    }

    // 使用switch
    switch (condition) {
    case 'case1':
    // do something
    break;
    case 'case2':
    // do something else
    break;
    default:
    // default case
    break;
    }

请注意,这些方法在不同的编程语言中可能有不同的实现方式,但核心思想是相同的。在JavaScript中,你可以使用Ramda库或Lodash库等来实现这些函数式编程模式。在其他语言中,如Haskell或Scala,函数式编程是内置的,并且有更多内置的函数式编程特性。

参考资料

[1]

首发平台: 非常感谢各位的点赞,关注和转发,你们的点赞和关注是我更新的动力。哔哩哔哩,知乎和墨滴平台同名账号。

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言