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


142

i并且j是非常流行的变量名(例如,参见此问题问题)。

例如,在循环中:

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

作为矩阵索引:

mat( i, j ) = 4;

为什么不将它们用作Matlab中的变量名?


5
当然,我不会将其标记为此类,但是从答案来看,我会说这是“主要基于意见的”。;-)我个人不放弃ijk作为通用的循环变量名。
A. Donda

1
@ A.Donda好吧,这是您的意见;)
Shai

@Shai,这是您在此问题中的最后一句话:“为什么不在Matlab中将它们用作变量名?” 因此,目前还不清楚为什么您在问题上拒绝我的版本?我将标题更改为更具建设性的标题“为什么不应该在Matlab
中将

Answers:


176

因为ij都是表示虚数单位的函数:

因此,一个名为i或的变量j将覆盖它们,从而可能无声地破坏执行复杂数学运算的代码。

可能的解决方案包括改为使用iijj作为循环变量,或1ii需要时代表虚部使用。


42
还值得注意的是,即使您没有破坏任何内容,仍然要花费执行时间来解析ij变量名。
Eitan T 2013年

14
@Eitan:您实际上可以在Matlab的JIT编译版本中以任何具体结论性的方式对此进行备份吗?我从来没有发现这种情况(调用for10亿次循环的简单测试显示,时序没有统计差异)。我们都知道有特殊的代码来处理的正是这种和使用比其他变量ij(和k?)实际上是稍微慢一些。确实存在的差异在现实生活中微不足道,甚至不存在。根本没有理由不使用它,i并且将它们j作为常规变量使用-只需像其他任何Matlab函数一样正确使用它们即可。
horchler 2013年

5
@horchler好吧,官方文档在这里指出,覆盖标准的MATLAB数据类“可能会对性能产生负面影响”,并且在这里暗示要避免由于速度和鲁棒性而覆盖复杂的常量。在R2009b的较旧文档中,强烈建议不要覆盖复杂常量,因为这可能会阻碍JIT加速。变量名解析可能很小,但如果重复数百万次,则可能意义重大。
Eitan T 2013年

14
在古老的Matlab版本中。我以前经常见到自己。但是至少对于R2012a +(OS X)而言不再如此。而且,当调用for10亿次循环并尝试各种计时方案时,我看不出有什么区别。我看到新的SO用户被告知完全有效的代码是错误的,因为他们正在使用ij迭代循环。坦率地说这只是愚蠢和人失踪这个问题的更重要的一点:ij甚至不应该被用于虚数单位如果想要写可读的现代Matlab代码。
霍希勒2013年

12
我主要节省的时间是在搜索ii时。搜索我可能是一个真正的痛苦
craq 2014年

62

避免i和避免j变量混淆是一个好习惯,因为它们是变量或虚数单位。

但是,就我个人而言,我经常将ij作为变量用作短循环的索引。为了避免我自己的代码中出现问题,我遵循了关于i和的另一种良好做法j请勿使用它们来表示虚数。实际上,Matlab自己的文档指出

对于速度和改进的鲁棒性,可以取代复杂的ij通过1i

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


2
使用确实是一个好习惯1i。然而,改变的意义i,并j可能导致诸如难以调试的错误这一个
Shai

1
@Shai好点。我调整了答案以确认避免ij最好,但解释了我的个人编码风格如何不遵循该规则。
shoelzer

2
请注意,所提到的速度似乎并不十分显著:stackoverflow.com/questions/18163454/...
丹尼斯Jaheruddin

完全同意!好的做法是始终使用1i而不是i复杂的数学。让我们把虚数看作是一个不好的做法1i,把i虚数当作虚数。并非相反。使用iiiiii是在Matlab常见的做法,有当人们坚持没有问题1i,并1j为复数。Matlab也尊重这一点,并且这不会降低性能(据我测试),正如先前答案中所述。
SdidS

无论如何,都不应使用i和j-这些数字表示某些含义-使用描述目的的名称(row_n,elementNo,listItemIndex等)。如此一来,人们就可以更轻松地了解您在做什么,要进行调试等。花费更多的时间来获得长期可维护性,这比一次性脚本要有价值的多,即使Matlab编辑器远远落后大多数其他现代IDE。
LightCC

27

在旧版本的MATLAB中,曾经有一个很好的理由避免使用ij作为变量名-早期版本的MATLAB JIT不够聪明,无法告诉您是将它们用作变量还是虚数单位,因此会关闭许多其他可能的优化。

因此,仅由于存在ij作为变量,您的代码就会变慢,如果将其更改为其他变量,则代码会加快速度。这就是为什么,如果您阅读了很多MathWorks代码,就会发现iijj广泛用作循环索引。有一阵子,MathWorks甚至可能非正式地建议人们自己去做(尽管他们总是正式建议人们去编程,以求优雅/可维护性,而不是为当前的JIT做任何事情,因为它是每个版本的目标)。

但这是很久以前的事了,如今它有点“僵尸”问题,其重要性远不如许多人想象的那么重要,但拒绝死亡。

在任何最新版本中,是否使用ij作为变量名实际上都是个人喜好。如果您对复数进行大量工作,则可能需要避免ij作为变量使用,以避免任何小的潜在混淆风险(尽管您可能也/反而只想使用1i1j为了减少混淆,而又想获得更好的性能) )。

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


我在这里看到很多回答,说“ 不推荐...”,而不是说谁在做这个推荐。以下是当前版本文档中MathWorks实际建议的范围i

由于i是一个函数,因此可以覆盖它并将其用作变量。但是,如果要在复杂的算术中使用它们,最好避免使用i和j作为变量名。为了提高速度和增强鲁棒性,您可以将复数i和j替换为1i。


15

如其他答案所述,由于i以下两个原因,不建议使用通用代码:

  • 如果要使用虚数,它可能会与索引混淆或覆盖
  • 如果将其用作索引,它可能会使虚数掩盖或混淆

如建议:1iii推荐。但是,尽管它们都与都有微小的偏差i,但同时使用这两种方法并不是很好。

这是一个为什么我个人不喜欢的示例:

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

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

因此,我个人的建议是:如果您有时使用复杂的代码,请始终1i将其与其他循环变量结合使用。

对于如果你不使用许多循环变量和字母就够了单个字母索引的例子:tukp

更长的指数例如:i_loopstepwalk,和t_now

当然,这也是个人喜好问题,但是在不增长太长时间的情况下,不难找到具有明确含义的索引。


1
1i表示虚数单位(Matlab变量名称也不能以数字开头)
lib

2
@DennisJaheruddin:无耻的插件:使用我的MATLAB语法高亮显示用户脚本进行堆栈溢出。在最后一个示例中,1i将以不同的颜色显示数字:)
Amro

2
直接来自doc idoc j:“为了提高速度和增强的鲁棒性,可以将复数i和j替换为1i。” IMO,在当前的Matlab中,没有理由不使用i而不是j在循环中等,或使用除1i表示虚数单位以外的任何方式使用(1j也可以使用)。唯一的例外是将字符串传递到始终略微不兼容的Symbolic引擎时。奇怪的是,help 1idoc 1i没有工作,虽然。
horchler 2013年

11

有人指出,这1i是一种可以接受且明确的书写方式sqrt(-1),因此不必避免使用i。话又说回来,丹尼斯指出(https://stackoverflow.com/a/14893729/1967396),它可以是很难看到的区别1iii。我的建议:1j尽可能使用虚常数。这是电气工程师采用的相同技巧-他们之所以使用jsqrt(-1)是因为i它已经消耗了电流

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


2
“它可以是很难看到的区别1iii”甚至更多的差异1l之间O0。这就是为什么我在全新的MATALB安装中要做的第一步就是更改默认字体大小。
glglgl 2014年

6

与虚构单元的混淆已在此处得到了很好的论述,但是还有其他一些比较平淡的原因,有时不鼓励使用这些名称以及其他单字母变量名称。

  1. 特别是MATLAB:如果您正在使用编码器从MATLAB代码生成C ++源代码(不要这样,那太可怕了),那么会明确警告您不要重复使用变量,因为可能会发生类型冲突。

  2. 通常,根据您的IDE,单字母变量名称可能会导致荧光笔和搜索/替换的混乱。MATLAB并不会因此而受苦,我相信Visual Studio已有一段时间没有出现问题了,但是MISRA等C / C ++编码标准倾向于向他们提出建议。

就我而言,尽管直接实现数学源具有明显优势,但我还是避免了所有单字母变量。最初几百遍,这会花费一些额外的精力,但此后您就不再注意到了,当您或其他可怜的灵魂来阅读代码时,它的好处是无数。


4

任何非平凡的代码都包含多个for循环,最佳实践建议您使用表示其目的和范围的描述性名称。对于远古时代(除非它的5〜10行,我救不了),我一直使用的变量名一样idxTaskidxAnotherTaskidxSubTask等。

或者至少将ss要索引的数组的第一个字母加倍,例如subjectListtt将index 索引到index taskList,但不是,ii或者jj这没有帮助我毫不费力地从my for循环中识别出它们正在索引哪个数组。


3

默认情况下ij代表虚构单位。因此,从MATLAB的角度来看,使用i变量就像使用1变量一样。


5
我认为不是那样。我是一个合法的变量名,因此您实际上可以使用i和j作为变量名。如先前的答案所述,它将掩盖虚构的含义。1不是合法变量名称。如果您从不使用复数,那就太好了。
thang

@thang就是为什么我说“有点喜欢”而不是“喜欢”。我知道有区别。OP问为什么不应该使用它们,我试图解释这是因为它们已经表达了一个数字。
2013年

2
好吧,对不起,我不知道是什么莫名其妙地喜欢手段。对我来说,这显然是不同的,因为好吧,即使您愿意也不能将1用作变量...但是我知道您来自哪里。
thang

可以使用它们,也可以将现有函数名称用于变量(同时破坏那些内置函数/常量以供进一步使用)。您是否真的想要那是另一回事(简单的回答:否)
Gunther Struyf,

1
抱歉,但是这种解释没有任何意义。的ij实际上是返回虚数单位的值的函数。可以在作用域中使用与函数同名的变量。但是,这将使功能蒙上阴影。
patrik

2

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

正如在其他帖子中提到的那样,对虚构单元进行阴影处理确实会在某些情况下引起某些混乱,但总的来说,我只是认为它不是主要问题。您可以在MATLAB中做更多令人困惑的事情,例如定义false=true

在我看来,唯一可能应该避免使用它们的地方是,如果您的代码专门处理虚数。


否决投票时,请您发表评论。例如,带有Mathworks链接的内容表明不推荐这种做法(已由多个发布者声明,未参考任何正式指南)。实际上,Mathworks在官方示例中使用了在循环中使用“ i”。以我的经验,它使代码清晰简洁,这是很常见的做法。
gregswiss 2015年

1
引用文档 “由于它i是一个函数,因此可以重写它并用作变量。但是,如果要在复杂的算术中使用它们,最好避免使用ij作为变量名。” 结合Eitan T对Oliver的回答的评论(我想他是定时的),这似乎是充分的证明。
Adriaan 2015年

1
另请注意,@ Adriaan提到的评论已经有2013年的答案
Andras Deak

1
因此,文档说明了您是否打算在复杂的算术中使用,否则就不适用-不知道为什么这里的每个人都这么挑剔!我只是提供了另一种观点。
gregswiss 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.