在 MATLAB 中使用 i 和 j 作为变量

Posted

技术标签:

【中文标题】在 MATLAB 中使用 i 和 j 作为变量【英文标题】:Using i and j as variables in MATLAB 【发布时间】:2013-01-25 06:59:42 【问题描述】:

ij 是非常流行的变量名称(参见例如 this question 和 this one)。

例如,在循环中:

for i=1:10,
    % Do something...
end

作为矩阵的索引:

mat(i, j) = 4;

为什么不应该在 MATLAB 中将它们用作变量名?

【问题讨论】:

当然我不会这样标记它,但从答案来看,我会说这是“主要基于意见”。 ;-) 我个人不会放弃 ijk 作为通用循环变量名。 @A.Donda 好吧,这是你的意见 ;) 【参考方案1】:

这里已经很好地涵盖了与虚数单位的混淆,但还有一些其他更平淡无奇的原因有时不鼓励使用这些和其他单字母变量名称。

    特别是 MATLAB:如果您使用 coder 从您的 MATLAB 代码生成 C++ 源代码(不要,这太可怕了),那么您会被明确警告不要重用变量,因为可能会发生键入冲突。

    通常,根据您的 IDE,单字母变量名可能会导致荧光笔和搜索/替换的严重破坏。 MATLAB 并没有受此困扰,我相信 Visual Studio 已经有一段时间没有出现问题了,但是像 MISRA 等 C/C++ 编码标准倾向于反对它们。

就我而言,我避免使用所有单字母变量,尽管直接实现数学源有明显的优势。前几百次需要额外的努力,但之后你就不会注意到了,当你或其他一些可怜的灵魂来阅读你的代码时,好处是很多的。

【讨论】:

【参考方案2】:

有人指出1i 是写sqrt(-1) 的一种可接受且明确的方式,因此没有必要避免使用i。再说一次,作为Dennis pointed out,很难看出1iii 之间的区别。我的建议:尽可能使用1j 作为假想常数。这与电气工程师使用的技巧相同——他们使用j 代替sqrt(-1),因为i 已经被用于current。

我个人从不使用ij;当我需要使用复数时,我使用 iijj 作为速记索引变量(以及 kk、ll、mm、...)和 1j

【讨论】:

"很难看出1iii 之间的区别" 甚至1l 之间以及O0 之间的区别。这就是为什么我在全新安装 MATALB 时所做的第一步是更改默认字体大小。【参考方案3】:

如其他答案中所述,不建议在一般代码中使用i,原因有两个:

如果您想使用虚数,它可能会与索引混淆或被索引覆盖 如果将其用作索引,它可能会覆盖或与虚数混淆

按照建议:推荐使用1iii。然而,尽管这两个都与i 有细微差别,但同时使用这两个替代方案并不是很好。

这是我(个人)不喜欢它的一个例子:

val2 = val + i  % 1
val2 = val + ii % 2
val2 = val + 1i % 3

一个不容易被两个或三个误读,但两个和三个彼此相似。

因此,我个人的建议是:如果您有时处理复杂的代码,请始终使用 1i 和不同的循环变量。

如果您不使用许多循环变量和字母就足够了的单字母索引示例:t,u,kp

较长索引的示例:i_loopstepwalkt_now

当然,这也是个人喜好问题,但不难找到可以使用且含义明确且不会增长太久的索引。

【讨论】:

1i 表示虚数单位(Matlab 变量名也不能以数字开头) @DennisJaheruddin:无耻插件:使用我的 MATLAB 语法高亮 userscript 进行堆栈溢出。在最后一个示例中,1i 将作为数字以不同的颜色显示 :) 直接来自 doc idoc j:“为了提高速度和提高稳健性,您可以将复数 i 和 j 替换为 1i。” IMO,在当前的 Matlab 中,没有理由不在循环中使用 ij 等,或者使用 1i 以外的任何东西来表示虚数单位(1j 也适用)。唯一的例外是在将字符串传递给总是稍微不兼容的符号引擎时。奇怪的是 help 1idoc 1i 不起作用。【参考方案4】:

最好避免使用ij 变量,以免混淆它们是变量还是虚数单位。

然而,我个人经常使用ij 作为变量作为短循环的索引。为避免我自己的代码出现问题,我遵循另一个关于 ij 的良好做法:不要使用它们来表示虚数。其实MATLAB's own documentation states:

为了提高速度和提高稳健性,您可以将复杂的 ij 替换为 1i

因此,我没有因为潜在的冲突而避免使用两个非常常用的变量名称,而是明确说明了虚数。它也使我的代码更清晰。每当我看到1i,我就知道它代表sqrt(-1),因为它不可能是一个变量。

【讨论】:

使用1i 确实是个好习惯。但是,更改ij 的含义可能会导致难以调试的错误,例如this one。 @Shai 好点。我调整了我的答案,承认最好避免使用 ij,但解释了我的个人编码风格如何不遵循该规则。 请注意,提到的速度似乎不是很重要:***.com/questions/18163454/… 完全同意!好的做法是始终使用 1i 而不是 i 进行复杂的数学运算。让我们将虚数视为1i,并将i 视为虚数是一种不好的做法。不是反过来。使用iiiiii是Matlab中的常见做法,当人们坚持使用1i1j作为复数时没有问题。 Matlab 也尊重这一点,并且这一点不会降低性能(据我测试),如上一个答案中所述。 i 和 j 无论如何都不应该使用 - 这些数字意味着 某事 - 使用描述目的的名称(row_n、elementNo、listItemIndex 等)。 所以让别人更容易理解你在做什么,调试等等。花费的额外时间比一次性脚本更值得长期可维护性的收益 - 甚至Matlab 编辑器远远落后于大多数其他现代 IDE。【参考方案5】:

任何重要的代码都包含多个for 循环,最佳做法建议您使用说明其用途和范围的描述性名称。在远古时代(除非我不会保存它的 5-10 行脚本),我一直使用变量名,如 idxTaskidxAnotherTaskidxSubTask 等。

或者至少将它正在索引的数组的第一个字母加倍,例如sssubjectList 进行索引,tttaskList 进行索引,但不是iijj,这并不能帮助我毫不费力地从我的多个 for 循环中识别出它们正在索引的数组。

【讨论】:

在 MATLAB 中最好避免显式循环(因为它非常慢)。很多东西都可以表示为矩阵和向量运算。【参考方案6】:

除非您是一个非常困惑的用户,否则我认为使用变量名称 ij 的风险很小,而且我经常使用它们。我没有看到任何官方迹象表明应该避免这种做法。

虽然像其他帖子中提到的那样,在某些情况下遮蔽虚数单位确实会引起一些混乱,但总的来说,我根本不认为这是一个主要问题。您可以在 MATLAB 中做更多令人困惑的事情,例如定义 false=true

在我看来,您唯一应该避免使用它们的情况是您的代码专门处理虚数。

【讨论】:

您能否在投反对票时发表评论。例如,有一个 Mathworks 链接表明不推荐这种做法(多张海报已经说明了这一点,但没有参考任何官方指南)。事实上,Mathworks 在官方示例中使用了循环中的“i”。以我的经验,它使代码清晰简洁,是非常普遍的做法。 引用documentation"由于i是一个函数,所以可以重写它作为变量使用。但是,变量名最好避免使用ij如果你打算在复杂的算术中使用它们。”再加上 Eitan T 对 Oliver 的回答(我猜是他计时)的评论,这似乎足以证明。 另请注意,@Adriaan 提到的评论中已经有an answer from 2013。 所以文档说明如果您打算在复数算术中使用,否则不适用 - 不知道为什么每个人都在这里如此挑剔!我只是提供另一种观点。【参考方案7】:

在旧版本的 MATLAB 中,过去有充分的理由避免使用 ij 作为变量名 - 早期版本的 MATLAB JIT 不够聪明,无法判断您是否将它们用作变量或虚数单位,因此会关闭许多其他可能的优化。

因此,仅将 ij 作为变量存在,您的代码就会变慢,如果您将它们更改为其他内容,代码会加快速度。这就是为什么如果您通读大量 MathWorks 代码,您会看到 iijj 被广泛用作循环索引。有一段时间,MathWorks 甚至可能非正式地建议人们自己做这件事(尽管他们总是正式建议人们为优雅/可维护性而编程,而不是按照当前 JIT 所做的任何事情,因为它是每个版本的移动目标)。

但那是很久以前的事了,现在它有点像“僵尸”问题,实际上远没有许多人认为的那么重要,但它拒绝死去。

在任何最近的版本中,是否使用ij 作为变量名确实是个人喜好。如果您使用复数进行大量工作,您可能希望避免将 ij 作为变量,以避免任何小的潜在混淆风险(尽管您可能也/相反只想使用 1i 或 @ 987654332@ 以减少混乱,并提高性能)。

另一方面,在我的典型工作中,我从不处理复数,如果我可以随意使用 ij 作为循环索引,我会发现我的代码更具可读性。


我在这里看到很多回答说 不推荐... 没有说明谁在推荐。以下是 MathWorks 的实际建议范围,来自 i 的当前版本文档:

由于 i 是一个函数,它可以被覆盖并用作变量。但是,如果您打算在复数算术中使用变量名,最好避免使用 i 和 j。 [...] 为提高速度和提高鲁棒性,您可以将复数 i 和 j 替换为 1i。

【讨论】:

【参考方案8】:

因为ij 都是表示imaginary unit 的函数:

http://www.mathworks.co.uk/help/matlab/ref/i.html http://www.mathworks.co.uk/help/matlab/ref/j.html

因此,名为 ij 的变量将覆盖它们,可能会默默地破坏执行复杂数学运算的代码。

可能的解决方案包括使用iijj 作为循环变量,或者在需要i 表示虚数单位时使用1i

【讨论】:

另外值得注意的是,即使你没有破坏任何东西,仍然会牺牲执行时间来解析ij变量名。 @Eitan:你真的可以在一个 JIT 编译版本的 Matlab 中以任何具体的结论性方式支持它吗?我从来没有发现过这种情况(调用for 循环 10 亿次的简单测试显示时间上没有统计差异)。据我们所知,有专门的代码来处理这个问题,并且使用ij(和k?)以外的变量实际上稍微慢一些。确实存在的差异在现实生活中是微不足道的。根本没有理由不使用 ij 作为常规变量 - 它们只需要像任何其他 Matlab 函数一样正确使用。 @horchler 好吧,官方文档声明 here 覆盖标准 MATLAB 数据类“会对性能产生负面影响”,而 here 暗示要避免覆盖复杂常量,因为速度原因,如以及鲁棒性。在older docs of R2009b 中明确建议不要覆盖复杂常量,因为这可能会阻碍 JIT 加速。变量名称解析可能微不足道,但如果重复数百万次,它可能会很重要。 可能在古代版本的 Matlab 中。我以前自己也看到过。但至少不再使用 R2012a+ (OS X)。在调用for 循环 10 亿次并尝试各种计时方案时,我没有发现任何区别。我看到新的 SO 用户被告知完全有效的代码是错误的,因为他们使用 ij 来迭代循环。坦率地说,这很愚蠢,人们错过了这个问题更重要的一点:如果想编写可读的现代 Matlab 代码,ij 甚至不应该用于虚数单位。 我主要节省的时间是在搜索 ii.寻找我可能是一个真正的痛苦【参考方案9】:

默认情况下,ij 代表虚数单位。所以从 MATLAB 的角度来看,使用 i 作为变量在某种程度上就像使用 1 作为变量一样。

【讨论】:

我不认为它是那样的。 i 是合法的变量名,因此您实际上可以使用 i 和 j 作为变量名。正如先前的答案所提到的,它将掩盖想象的含义。 1 不是合法的变量名。如果你从不使用复数,那完全没问题。 @thang 这就是为什么我说“有点像”而不是“喜欢”。我知道有区别。 OP问为什么不应该使用它们,我试图解释这是因为它们已经表达了一个数字。 好的,抱歉,我不知道 somewhere like 是什么意思。对我来说,这显然是不同的,因为即使你愿意,你也不能使用 1 作为变量......但我知道你来自哪里。 可以使用它们,因为您也可以将现有的函数名称用于变量(同时破坏这些内置函数/常量以供进一步使用)。你是否真的想要那是另一回事(imo简单回答:否) 抱歉,这种解释毫无意义。 ij 实际上是返回虚数单位值的函数。可以使用与作用域中的函数同名的变量。然而,这会影响函数。

以上是关于在 MATLAB 中使用 i 和 j 作为变量的主要内容,如果未能解决你的问题,请参考以下文章

matlab怎么定义一个数组

MATLAB中for循环变量值不增加

matlab函数中如何获取变量的值比如这段程序我想知道执行后a1和a2的值怎么办啊?

求大神啊!matlab可以在循环体中改变循环变量来改变循环次数吗?如何进行呢?

matlab中cell数组问题

Matlab中的冒号