下标索引必须是实际的正整数或逻辑值,通用解决方案

41

以下错误经常发生:

下标索引必须是实际正整数或逻辑值

我发现有很多关于此问题的问题,但没有一个真正通用的答案。因此,我希望能得到处理此问题的通用解决方案。


我建议将这个QA扩展到另外两个非常相关的错误。请考虑以下内容:>> mean=1:4; >> mean(12) Index exceeds matrix dimensions. >> mean(12); Attempted to access mean(12); index out of bounds because numel(mean)=4. 第一个是“Index exceeds matrix dimensions”错误,当意外将变量命名为内置变量并尝试将内置变量用作函数时会出现此错误。第二个是一种奇怪的变体,只是提供了有关相同错误的更多详细信息。 - chappjc
@chappjc 虽然这些错误是相关的,但本文的主要目的是帮助那些遇到这个特定错误信息的人。当然,为每个常见的错误信息找到/创建一个好的参考问题和答案可能是一个好主意。 - Dennis Jaheruddin
2
好的观点。最好保持专注,尽管解决方案大致相同(如下第2点)。 - chappjc
3个回答

62

下标索引必须是实数正整数或逻辑值

几乎所有情况下,此错误都是由以下两个原因之一导致的。幸运的是,这有一个简单的检查方法。

首先,请确保您已经到达发生错误的行,通常可以在运行函数或脚本之前使用dbstop if error来实现。现在我们可以检查第一个问题:

1. 某处使用无效的索引访问变量

查找每个变量,并查看它们如何被索引。被索引的变量通常具有以下一种形式:

variableName(index,index)
variableName{index,index}
variableName{indices}(indices)

现在只需要看括号中的内容,选择每个索引。然后按下 f9 来计算结果并检查它是否是一个实际的正整数或逻辑值。通常目视检查即可(请记住可接受的值为 true、false 或 1、2、3...但不包括 0),但对于大型矩阵,您可以使用诸如 isequal(index, round(index)),或更精确地说,isequal(x, max(1,round(abs(x)))) 来检查实际的正整数。要检查类别,您可以使用 class(index),如果值全部为 'true' 或 'false',则应返回“logical”。

一定要检查每个索引,即使它们看起来不寻常,如下面的例子所示。如果所有索引都没有问题,则可能遇到第二个问题:

2. 函数名称已被用户定义的变量掩盖

MATLAB 函数通常具有非常直观的名称。这很方便,但有时会意外地重载(内置)函数,即创建与函数相同名称的变量,例如,您可以输入 max = 9 ,对于您的脚本/函数的其余部分,Matlab 将认为 max 是一个变量,而不是函数 max ,因此如果您尝试像 max([1 8 0 3 7]) 这样的操作,您将会得到一个错误,因为Matlab现在假设您正在索引变量max,而0是无效索引。

为了检查您拥有哪些变量,您可以查看工作区。但是,如果您正在寻找一种系统性的方法,请参考以下步骤:

对于每个带括号 () 的字母或单词,并且在第一步中未经确认具有适当的索引,请检查它是否实际上是一个变量。这可以通过使用 which 轻松完成。


示例

无效索引的简单出现

a = 1;
b = 2;
c = 3;
a(b/c)

在这里,我们将评估b/c并发现它不是一个漂亮的四舍五入数。

无效索引的复杂出现

a = 1;
b = 2;
c = 3;
d = 1:10;
a(b+mean(d(cell2mat({b}):c)))

我建议从内向外工作。所以首先评估被索引的最内部变量:d。结果表明,cell2mat({b}):c 很好地计算为整数。然后评估 b+mean(d(cell2mat({b}):c)),并发现我们没有一个整数或逻辑作为索引到 a

在这里,我们将评估 b/c 并发现它不是一个漂亮的圆整数字。

重载了一个函数

which mean 
% some directory\filename.m

你应该看到类似于这样的东西,以实际确认某个东西是一个函数。

a = 1:4;
b=0:0.1:1;
mean(a) = 2.5;
mean(b);

在这里我们看到mean被意外地赋值了。现在我们得到:

which mean
% mean is a variable.

1
很好的回答。您可能需要为使用ij作为循环变量添加特定的警告,因为它们在分配之前已经是虚数单位。(这并不是要反对使用ij作为变量名,仅仅是一个观察结果,因为我经常看到其中一个是这个错误的罪魁祸首。) - Adriaan

5
在Matlab(以及大多数其他编程语言中)必须始终写乘法符号。虽然在你的数学课上,你可能学过可以写成a(a+a)而不是a*(a+a),但在Matlab中这并不相同。前者是索引或函数调用,而后者是乘法。
>> a=0

a =

     0

>> a*(a+a)

ans =

     0

>> a(a+a)
Subscript indices must either be real
positive integers or logicals.

虽然这种情况在我的回答的第一点中已经隐含涵盖,但我喜欢额外提供一个示例来说明它是如何发生的。在此添加评论以帮助搜索“在进行乘法时,下标必须是实际正整数或逻辑值”的人们。 - Dennis Jaheruddin

4
到目前为止,对这个问题的回答都着重于这个错误的来源,这很好。但是了解 Matlab 中矩阵索引的强大而直观的特性非常重要。因此,理解 索引的工作原理什么是有效的索引 将有助于通过使用有效的索引来避免此错误。
在其核心中,给定长度为 n 的数组 A,有两种索引方式:
1. 线性索引:使用从 1 到 n 的整数子集(允许重复)。0 不允许出现,因为 Matlab 数组是基于 1 的,除非您使用下面的方法。对于高维数组,多个下标在内部会 转换为线性索引,但是以一种高效和透明的方式进行。
2. 逻辑索引:其中你使用一个长度为 n 的由 0 和 1 组成的数组,选取那些索引为 true 的元素。在这种情况下,unique(index) 必须只含有 0 和 1。
因此,一个有效的索引数组可以是另一个具有 n 个元素的数组:
  1. 完全逻辑相同大小的数组,或
  2. 线性子集整数从1:n

请记住,当您混合两种类型的索引时会出现无效的索引错误:在您的线性索引数组中出现一个或多个零,或者您将0和1与除0和1以外的任何东西混合使用 :)

有大量在线资料可以学习,包括这个网址: http://www.mathworks.com/company/newsletters/articles/matrix-indexing-in-matlab.html


总的来说,这是一个不错的解释,我并不想打击你的积极性,但似乎你实际回答特定问题的部分已经被涵盖了。因此,我认为这应该是一条评论,而不是一个答案。(我没有标记它,因为它太长了,无法转换为评论,但请记住这一点,以备将来发布)。 - Dennis Jaheruddin
谢谢Dennis。我考虑了你的观点,是否应该浪费我的时间(如果没有太大的贡献,可能会浪费其他人的时间),并决定这将提高人们未来的能力。如果有的话,也许你可以将它移动到一些元位置,作为Matlab教程/提示的核心要素。 - Pradeep Reddy Raamana

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接