MATLAB使用Pre-Matlab算法编写规范

肖卓2024年9月18日
大约 9 分钟

一、编码规范

**变量命名**

1. 变量名应使用小驼峰命名法,即第一个单词的首字母小写,后续单词首字母大写。 例如:velocity, angularAcceleration. 2. 作用域大的变量应该用有意义的名称。 作用域较小的变量可以用短名称。 例如:x, y, z 3. 前缀 n 应用于表示对象数量的变量。 例如:nFiles, nCars, nLines 4. 复数形式的约定 例如:point, pointArray 5. 代表单个实体编号的变量可以以编号No为后缀。 例如:tableNo, employeeNo 6. 迭代器变量应以 i、j、k 等命名或前缀。 iFiles, jColumns 7. 对于嵌套循环,迭代器应按字母顺序排列,并提供有用的名称。
for iFiles = 1:nFiles
 for jPositions = 1:nPositions 
 ...
 end 
end
  1. 避免使用否定的布尔变量名
    例如使用 isFound 而非 isNotFound
  2. 首字母缩略词即使通常为大写,也应混合或小写。
    html, isUsaSpecific
  3. 避免使用关键字或特殊值名称

**常量**

1. 命名常量应全部大写,并使用下划线分隔单词。 MAX_ITERATIONS, COLOR_RED 2. 常量可以使用通用类型名称作为前缀。 COLOR_RED, COLOR_GREEN, COLOR_BLUE

**结构体**

1. 结构体名称应使用大驼峰命名法,即每个单词的首字母都大写。 例如:Car, DumpTruck 2. 请勿在字段名称中包含结构体名称。 即使用 Segment.length 而不是 Segment.segmentLength

**函数**

1. 函数的名称应记录其用法,名称应该用小写或混合大小写。 width(), computeTotalWidth() 2. 函数应该使用有意义的名称,例如使用computeTotalWidth而非compwid 3. 具有单一输出的函数可以根据输出来命名 例如:shearStress(), standardError() 4. 没有输出参数或仅返回句柄的函数应根据其功能来命名。 例如:plotfft() 5. 为访问对象或属性保留前缀get/set。 例如:getobj(), setappdata() 6. 为计算某些内容的方法保留前缀compute。 例如:computeSumOfResiduals(), computeSpread() 7. 为查找内容的方法保留前缀find。 例如:findOldestRecord() 8. 保留前缀initialize用于实例化对象或概念。 例如:initializeProblemState() 9. 为布尔函数保留前缀is。 例如:isCrazy, isNuts, isOffHisRocker 10. 当为彼此密切相关的概念或操作创建有意义的名称时,最好使用强相关的名称。当其中一个操作与另一个操作相反或互补时尤其如此。 例如:get/set, add/remove, create/destroy, start/stop, insert/delete, increment/decrement, old/new, begin/end, first/last, up/down, min/max, next/previous, open/close, show/hide,suspend/resume等 11. 需要注意函数名同名问题,可使用which -all 或exist 来检查是否存在函数名遮蔽。

**文件**

**M文件**

1. 将代码模块化,使用片段来组成整体。 2. 编写易于测试的函数。 3. 明确交互。使用输入和输出而不是全局变量。用结构代替长长的参数列表。 4. 分区。所有子函数和大多数函数都应很好地完成一件事。 5. 尽可能使用现有函数,而不是自定义编码函数。 6. 将多个 m 文件中使用的代码块移至函数中。 7. 当一个函数只被一个其他函数调用时,使用子函数。 8. 为每个函数编写测试脚本。

**声明**

**变量和常量**

1. 除非内存限制要求,否则不应重复使用变量。 2. 同一类型的相关变量可以在共同语句中声明。不相关的变量不应在同一语句中声明。 persistent x, y, z 3. 在文件开头附近的注释中记录重要变量。用行末注释记录常量。 THRESHOLD = 10; % Max noise level

**全局变量**

尽量减少全局变量和常量的使用。考虑使用函数替代全局常量。

**循环**

1. 循环中使用的变量应在循环之前立即初始化。
result = zeros(nDays,1);

for iDay = 1:nDays

 result(iDay) = foo(iDay);

end
  1. 尽量减少在循环中使用break 和 continue 。

  2. 嵌套循环中的结束行可以用注释来阐明代码块。

for index=1:2 
 if index==1 
  dosomething(index); ... 
 end % End if 
end % End for

**条件式**

1. 避免复杂的条件表达式,改用临时逻辑变量。
isValid = (v >= lowerLimit) & (v <= upperLimit); 
isNew = ismember(v, valueArray);
  1. 避免使用条件表达式 if 0。
  2. if-else 序列应包含 else 条件。
    通常情况应放在if部分,例外情况应放在if-else语句的else部分。
  3. switch 语句应包含 otherwise 条件。
  4. 如果变量是字符串,请使用switch序列。
  5. 尽可能使用switch语句代替多重if-elseif-else语句。

**布局、注释和文档**

**布局**

1. 内容应保留在前 80 列内。 2. 应在逗号、空格和运算符之后分割行。 3. 续行与上一行表达式的开头对齐

例如:

totalSum = a + b + c ... 
           d + e;
  1. 基本缩进应为 4 个空格。
  2. 一般来说,一行代码应该只包含一个可执行语句。
  3. 短的单语句 if、for 或 while 语句可以写在一行上。
if (condition), statement; end

**空格**

1. 在 = 、& 和 | 前后插入空格。 2. 逗号后跟一个空格。 3. 关键字后面应该跟一个空格。 4. 代码块应由三个空行或分节符分隔。 5. 在任何可以增强可读性的地方使用对齐代码。

**注释**

1. 注释应该与代码一致,但不能重复代码。 2. 注释应与引用的语句具有相同的缩进。 3. 传统的函数头注释应支持 help 和 lookfor,在matlab中使用help + 函数名会打印该函数的第一个连续的注释块。

  1. 使用lookfor+函数命令的方式,查看某一函数的介绍。在命令行窗口输入lookfor plot,此时将出现所有与plot函数有关的M文件。

  1. 函数头注释应该讨论输入/输出参数的任何特殊要求,并描述函数的任何副作用。在函数头注释中使用正确的大小写编写函数名称。
function runEverything 
% runEverything runs all mfiles in its folder
  1. 将任何版权行和更改历史记录放在函数标题之后,中间空一行。
  2. 所有注释均应使用英文。

**文档**

1. 使用文本标记编写页眉注释,提供用户文档。包含与帮助页面相对应的部分:语法、描述、示例和另见。考虑先编写文档,以便更好地定义输入、输出和功能。 2. 考虑使用 SVN 或 GIT 等源代码控制工具。如果不使用源控制工具,可在函数标题后或脚本顶部附近添加更改历史注释,以记录更改。

二、算法规范

算法一般由算法主文件、关联函数文件、数据文件和示例文件四部分组成。

算法主文件

算法主文件必须提供一个函数,函数中明确输入参数和输出参数,并使用注释进行说明,通常函数名可以使用main进行命名,主函数内部应使代码模块化的方式组成一个整体,当计算逻辑比较复杂的时候,应该将该代码块移到一个函数中。
% 计算光伏板逐时功率的函数
% 输入参数
% geoFilepath: GeoJSON 文件,计算总面积
% panelEfficiency: 光伏板效率 1*1
% shadingFactor: 遮荫影响系数 (1*1, 0-1 之间)
% solarIntensityFile: 逐小时日照强度数据文件
% 输入参数
% hourlyPower: 逐时功率 8760*1
function hourlyPower = main(geoFilepath, panelEfficiency, shadingFactor, solarIntensityFile)
    data = load(solarIntensityFile); % 加载日照数据文件
    solarIntensityData = data(:, 5); % 取文件中第5列数据,获取逐时的日照强度
    if length(solarIntensityData) ~= 365 * 24
        error('数据长度不匹配:需要一年的逐小时日照强度数据(8760 行)。');
    end
    solarIntensityData = solarIntensityData / 1000; % 将日照强度的单位从wh提高到kwh
    hourlyPower = zeros(length(solarIntensityData), 1); % 初始化返回参数,提高效率
    panelArea = calculateTotalArea(geoFilepath); % 调用计算面积函数,输入geo面积文件路径,输入面积值
    for hour = 1:length(solarIntensityData) 
        currentSunIntensity = solarIntensityData(hour);
        currentSunIntensityWatt = currentSunIntensity * 1000;
        effectiveSunIntensity = currentSunIntensityWatt * (1 - shadingFactor);
        hourlyPower(hour) = panelArea * panelEfficiency * effectiveSunIntensity;
    end % 循环计算每小时光伏板功率
end

关联函数文件

在主函数中调用的计算面积函数calculateTotalArea()
% 计算面积
% filepath: 建模导出的面积文件路径
% totalArea: 面积 1*1
function totalArea = calculateTotalArea(filepath)
    fid = fopen(filepath, 'r');
    raw = fread(fid, inf);
    str = char(raw');
    fclose(fid);
    data = jsondecode(str);
    totalArea = 0;
    for i = 1:length(data.features)
        if isfield(data.features(i).properties, 'Area')
            totalArea = totalArea + data.features(i).properties.Area;
        end
    end
end

数据文件

数据文件一般是mat格式或者dat格式,打开后如下

示例文件

示例文件中主要展示了如何调用各函数的代码,理论上每个函数都应该有一个测试脚本,实际开发过程中只需要提供主函数和复杂函数的的测试脚本即可。
% Sample script to demonstrate execution of function hourlyPower = main(geoFilepath, panelEfficiency, shadingFactor, solarIntensityFile)
geoFilepath = 'C:\Users\xiao\Downloads\measurements.geojson'; 
panelEfficiency = 0.2089; % 单晶硅 
shadingFactor =  0.2; % 遮荫系数
solarIntensityFile = 'zhoushangang-hour.dat';
hourlyPower = main(geoFilepath, panelEfficiency, shadingFactor, solarIntensityFile);
disp(hourlyPower);

三、算法编译

编译后的算法可以在其他的平台进行调用,目前我们项目中常用的方式是jar包调用,所以简单介绍一下打包方式,可以测试编写完成的算法是否正常。

编译环境安装

官方文档:[https://ww2.mathworks.cn/help/compiler_sdk/java/configure-your-java-environment.html](https://ww2.mathworks.cn/help/compiler_sdk/java/configure-your-java-environment.html)

编译前需要安装java的JDK并添加环境变量,在环境变量中添加JAVA_HOME,而且还需要检查注释中是否有特殊字符

编译文件

官方文档:[https://ww2.mathworks.cn/help/compiler_sdk/gs/create-a-java-application-with-matlab-code.html](https://ww2.mathworks.cn/help/compiler_sdk/gs/create-a-java-application-with-matlab-code.html)

在APP下找到LibraryCompiler,进入编译界面

在编译界面添加主函数文件,选择Java Package

添加测试文件,修改类名,点击Package进行打包

如果代码没有问题,则直接弹出打包完成

上次编辑于: 2024/9/18 16:07:54
贡献者: 肖卓
评论
Powered by Waline v2.5.1