arrays - index - ¿Matlab acepta índices no enteros?
scalar octave (1)
¡Por supuesto no! ... ¿O sí? Vamos a hacer algunas pruebas.
Defina x = [10 20 30 40 50]
. Entonces, cualquiera de las siguientes afirmaciones, como se esperaba, da un error en Matlab (los índices de subíndices deben ser números enteros positivos reales o lógicos ):
>> 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)
Sin embargo, los valores no enteros se aceptan en los índices de colon . Todo el trabajo siguiente en versiones recientes de Matlab, aunque con una advertencia ( se requieren operandos enteros para el operador de dos puntos cuando se usa como índice ).
>> 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
También funciona si la expresión de dos puntos incluye end
:
>> x(1.5:end-2)
ans =
20 30
>> x(1.5:end/6:end-1)
ans =
20 20 30 40
Por otro lado, los siguientes no funcionan y dan el mismo error que el anterior:
>> x(-0.6:2)
>> x(-0.5:2)
El comportamiento observado se puede resumir de la siguiente manera:
- Algunos redondeos internos se activan cuando se utiliza un índice de dos puntos . Un índice de dos puntos es una expresión de la forma
a:b
oa:b:c
. No se produce redondeo cuando la matriz de indexación es una matriz estándar, como[abc]
o incluso[a:b]
o[a:b:c]
. - El redondeo se realiza al entero más cercano , excepto que los números entre
-0.5
y0.5
tienen un recuadro especial : se redondean a1
lugar de a0
. Por supuesto, si el entero resultante del redondeo es negativo, se produce un error.
Se observa un comportamiento similar en las versiones recientes de Octave, excepto que:
Aparentemente, se realiza el redondeo normal al entero más cercano, sin tratar los números entre
-0.5
y0.5
como un caso especial; y entonces estos dan un error:>> x(0.4:3) >> x(-0.4:3)
Se emite un error cuando el rango no entero contiene un solo valor:
x(2.4:4)
funciona, perox(3.4:4)
no (por supuesto,x([2.4 3.4])
yx(3.4)
don tampoco funciona).
Aparte de esto, los resultados son los mismos que en Matlab, y también se emite una advertencia ( rango no entero utilizado como índice ).
Las advertencias y el hecho de que Octave funciona de manera similar a Matlab sugieren que este es el comportamiento previsto . Está documentado en alguna parte? ¿Alguien puede dar más información o arrojar algo de luz sobre esto?
Observaciones adicionales:
x(1.2:3)
debe interpretarse teóricamente como:subsref(x, substruct(''()'',1.2:3))
. Sin embargo, como se menciona en la pregunta, " No se produce el redondeo cuando la matriz de indexación es una matriz estándar ", lo que hace que falle la referencia explícitamente suscripta. Esto sugiere que tiene lugar un mecanismo similar a un cortocircuito lógico o quizás una partición multiproceso (donde la variable intermedia "no se crea realmente").El identificador de la advertencia emitida es
MATLAB:colon:nonIntegerIndex
.
Teorías
- Quizás existan versiones sobrecargadas de la referencia con subíndices, donde hay un paso inicial para detectar si los subíndices son enteros o no. En caso de que no lo sean, MATLAB "redirige" esto a alguna otra familia de clases ( example ).
Comentarios oficiales:
- Esto es lo que Steve Eddins de TMW tuvo que decir sobre el tema:
... en sus primeros días, los implementadores de MATLAB tenían una tendencia a ser lo más permisivos posible con respecto a la validación de entrada. Con el tiempo, nos dimos cuenta de que esta filosofía no siempre era la mejor para los usuarios, y comenzamos a hacer algunas de las reglas del lenguaje más estrictas y más regulares. Un ejemplo fue la introducción de mensajes de error sobre índices inválidos (no enteros, no positivos, etc.). Sin embargo, no siempre pudimos ajustar el comportamiento tanto como quisiéramos. A veces eso se debía a que descubrimos que un código de usuario demasiado explotaba el comportamiento original. Esa es una de las razones por las que continúa viendo este tipo de variación de comportamiento en algunos lugares. ... Aconsejaría a los usuarios que solo utilicen índices con valores enteros. Los usuarios pueden llamar explícitamente a round o floor o lo que sea para convertir la salida del operador de dos puntos a valores enteros.