How does sub2ind work with non-integer values?
Show older comments
I was working with some displacement matrices and noticed sub2ind working with non-integer inputs. It not only works but also outputs non-integer values. I looked at the documentation but didn't see an explanation for this behavior.
For example:
sub2ind([2 2],1,1.8)
So, if I round the output to 3, is it going to be the linear index that is closest to (1,1.8) based on Euclidean distance? What is the intended behavior here?
Thanks in advance and apologies if I missed this in the documentation.
12 Comments
Stephen23
on 21 Jul 2025
"How does sub2ind work with non-integer values?"
Open the M file and take a look, its algorithm is very simple.
"What is the intended behavior here?"
Most likely that users do not supply fractional values.
John D'Errico
on 21 Jul 2025
Edited: John D'Errico
on 21 Jul 2025
I wish I could have upvoted the @Stephen23 comment, because fractional values are not expected, and that sub2ind was never intended to be used in that way. I suppose they might have put in some additional error checks to flag such an issue, but at some point, additional error checks just suck away additional CPU cycles. And if you are using sub2ind, I have a funny feeling that those additonal unwarranted error checks will be almost always unappreciated.
"They could have checked to make sure it's an integer instead."
Integers can be negative, which does not really help things either.
"This could be an unintended behavior that is hiding in your codebase right now giving wrong results that you are not aware of."
Make a bug report (or enhancement request, depending on how you look at it):
Open the M file and take a look, its algorithm is very simple.
I'll just take this opportunity once again to say how amazing it is that sub2ind and ind2sub still haven't been reimplemented as optimized builtins, considering how frequently they are used, and how important they are to fast performance. Certainly if speed is the reason a check for integer-ness was omitted, it seems all the more sensible to abandon the Mcoded version.
Paul
on 22 Jul 2025
Is there a use case for sub2ind where its output is not used for a subsequent indexing operation?
Saygin
on 22 Jul 2025
Walter Roberson
on 22 Jul 2025
You need to round the coordinates to get the correct output:
There are no "correct results" for using sub2ind with non-integers. It is inherently a wrong thing to do.
Paul
on 22 Jul 2025
I wonder if the developers assumed that the output of sub2ind would be used only for indexing and were therefore relying on the non-integer case to throw an error downstream when used in an actual indexing operation.
I can't see how any application other than indexing would be envisioned by the developers. The "ind" in sub2ind stands for indexing.
It's also worth noting that ind2sub does not invert sub2ind when non-integer arguments are permitted
k=sub2ind([2 2],1,1.8)
[i,j]=ind2sub([2 2],k)
David Goodmanson
on 25 Jul 2025
Edited: David Goodmanson
on 25 Jul 2025
Hi Matt, after you commented on noninversion I added some material on the topic (more or less) in my answer below.
"I wonder if the developers assumed that the output of sub2ind would be used only for indexing and were therefore relying on the non-integer case to throw an error downstream when used in an actual indexing operation."
If that were the case, I guess it would have been a mistake insofar as a valid output can be obtained from an invalid input
sub2ind([100,100],61,10)
sub2ind([100,100],11,10.5)
Answers (1)
David Goodmanson
on 21 Jul 2025
Edited: David Goodmanson
on 25 Jul 2025
Hi Saygin,
Interesting behavior. The help for sub2ind says it 'returns the linear index equivalent' and I guess they really mean it about the linear part. For 2d, If the input matrix size is mxn and the input indices are p,q then the result is
sub2ind([m,n],p,q) = p + (q-1)*m
so long as 1<=p<=m and 1<=q<=n, even if none of them (including m and n) are integers. Evidently Matlab only checks the inequalities just listed, not for being integers.
---------
Matt's comment 'ind2sub does not invert sub2ind when non-integer arguments are permitted' brought up the idea of what kind of process could be inverted.
Suppose the matrix is size mxn, and r and c are row and column indices. ind2sub allows any of those four quantities to be noninteger. Let j be the index,
j = sub2ind([m n],r,c)
and let k be the index you would get if you read the matrix out rowwise rather than columnwise. Or if you prefer, by reading out the transposed version in the usual manner,
k = sub2ind([n m],c,r)
Let 'bar' quantities be one less than actual quantites; rbar = r-1 etc. Turn r and c into a 2x1 vector, same with j and k. Then there is a nice relationship among the barred quantities
m = 3.4; n = 2.7; r = 3.1; c = 1.8;
j = sub2ind([m n],r,c)
s2i = [1 m;n 1];
rcbar = [r;c]-1;
jkbar = s2i*rcbar; % fwd
jk = jkbar+1 % jk(1) = j
rcbar = s2i\jkbar; % inv
rc = rcbar+1 % agrees
j = 5.8200
jk = 5.8200
7.4700
rc = 3.1000
1.8000
Categories
Find more on Matrix Indexing in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!