31
votes

Of course not! ...Or does it? Let's do some tests.

Define x = [10 20 30 40 50]. Then any of the following statements, as expected, gives an error in Matlab (Subscript indices must either be real positive integers or logicals):

>> x(1.2)
>> x(-0.3)
>> x([1.4 2 3])
>> x([1.4 2.4 3.4])
>> x([1.4:4])
>> x(end/2)

However, non-integer values are accepted in colon indices. All of the following work in recent Matlab versions, although with a warning (Integer operands are required for colon operator when used as index).

>> x(1.2:3)
ans =
    10    20

>> x(0.4:3)
ans =
    10    10    20

>> x(0.6:3)
ans =
    10    20    30

>> x(1.2:0.7:5)
ans =
    10    20    30    30    40    50

>> x(-0.4:3)
ans =
    10    10    20    30

It also works if the colon expression includes end:

>> x(1.5:end-2)
ans =
    20    30

>> x(1.5:end/6:end-1)
ans =
    20    20    30    40

On the other hand, the following do not work, and give the same error as above:

>> x(-0.6:2)
>> x(-0.5:2)

The observed behaviour can be summarized as follows:

  • Some internal rounding kicks in when a colon index is used. A colon index is an expression of the form a:b or a:b:c. No rounding takes place when the indexing array is a standard array, such as [a b c] or even [a:b] or [a:b:c].
  • Rounding is done to the nearest integer, except that numbers between -0.5 and 0.5 are special-cased: they are rounded to 1 instead of to 0. Of course, if the integer resulting from the rounding is negative an error occurs.

Similar behaviour is seen in recent versions of Octave, except that:

  • Apparently, normal rounding to the nearest integer is done, without treating numbers between -0.5 and 0.5 as a special case; and so these give an error:

    >> x(0.4:3)
    >> x(-0.4:3)
    
  • An error is issued when the non-integer range contains a single value: x(2.4:4) works, but x(3.4:4) doesn't (of course, x([2.4 3.4]) and x(3.4) don't work either).

Other than this, the results are the same as in Matlab, and a warning is also issued (Non-integer range used as index).

The warnings and the fact that Octave works similarly as Matlab suggest that this is intended behaviour. Is it documented somewhere? Can anyone give more infromation or shed some light on this?

1
what version of matlab/octave are you using? with R2009a it does not work... Can anyone check other versions as well?Shai
My R2014b acts like as @Luis described the Octave behavior. It accepts all but x(0.4:3) and x(-0.4:3).Adiel
@Shai That's interesting. I've edited my question to mention that it only happens in recent versions. See some more tests hereLuis Mendo
wait... what?Ander Biguri
@LuisMendo regarding Octave, see the end of this pageTasos Papastylianou

1 Answers

7
votes

Additional observations:

  • x(1.2:3) should theoretically be interpreted as: subsref(x, substruct('()',1.2:3)). However, as mentioned in the question, "No rounding takes place when the indexing array is a standard array", which causes the explicit subscripted reference to fail. This suggests that a mechanism similar to logical short-circuiting or perhaps multithreaded partitioning (where intermediate variable are "not really created") takes place.

  • The issued warning's identifier is MATLAB:colon:nonIntegerIndex.

Theories:

  • Perhaps there exist overloaded versions of the subscripted reference where there is an initial step of detecting whether the subscripts themselves are integers or not. In case they're not, MATLAB "redirects" this to some other family of classes (example).

Official comments:

  • This is what Steve Eddins of TMW had to say on the subject:

    ... in its earliest days, MATLAB implementers had a tendency to be as permissive as possible with respect to input validation. Over time, we realized that this philosophy wasn’t always the best one for users, and we started making some of the language rules tighter and more regular. One example was the introduction of error messages about invalid indices (noninteger, nonpositive, etc.). However, we couldn’t always tighten up the behavior as much as we liked. Sometimes that was because we discovered that too much user code was exploiting the original behavior. That is one of the reasons you continue to see this kind of behavior variation in some places. ... I would advise users to only use integer-valued indices. Users can explicitly call round or floor or whatever to convert the output of the colon operator to be integer-valued.