2010-10-13 11 views
12

Deje x=1:100 y N=1:10. Me gustaría crear una matriz x^N para que la columna ith contenga las entradas [1 i i^2 ... i^N].Vectorizar la creación de una matriz de poderes sucesivos

Puedo hacer esto fácilmente con lazos for. Pero, ¿hay alguna forma de hacerlo utilizando código vectorizado?

+4

1 para tener la oportunidad de ver todos estos diferentes enfoques. – zellus

Respuesta

11

me gustaría ir para:

x = 1:100; 
N = 1:10; 
Solution = repmat(x,[length(N)+1 1]).^repmat(([0 N])',[1 length(x)]); 

Otra solución (probablemente mucho más eficiente):

Solution = [ones(size(x)); cumprod(repmat(x,[length(N) 1]),1)]; 

O incluso:

Solution = bsxfun(@power,x,[0 N]'); 

Espero que esto ayude.

+0

+1 para bsxfun + puntero de función + argumentos simples. Si puede expresar la regla de forma compacta, es probable que esa combinación le permita expresarla en MATLAB ... –

+0

+1 para bsxfun() vudú. @Adrien, creo que hay un error tipográfico: N = 1:10; en lugar de N = 1: 0; – zellus

+0

@zellus: cierto, error ortográfico corregido – Adrien

2

No estoy seguro si realmente se ajusta a su pregunta.

bsxfun(@power, cumsum(ones(100,10),2), cumsum(ones(100,10),1)) 

EDIT: Como ha señalado Adrien, mi primer intento no era compatible con la pregunta OP.

xn = 100; 
N=10; 
solution = [ones(1,xn); bsxfun(@power, cumsum(ones(N,xn),2), cumsum(ones(N,xn),1))]; 
+0

La primera línea de la matriz computex debe ser una, en su caso es '1: 100 ' – Adrien

5

Desde sus matrices no son tan grandes, el camino más directo para hacer esto sería utilizar MESHGRID y la element-wise power operator.^:

[x,N] = meshgrid(1:100,0:10); 
x = x.^N; 

Esto crea una matriz de 11 por 100 en la que cada uno La columna i contiene [i^0; i^1; i^2; ... i^10].

+2

nice meshgrid use. Mi único problema con este método y los similares propuestos aquí es que no usan la línea i^th para calcular la línea i + 1 a bajo costo. La variante de cumpro lo hace pero falta algo de estética. – Adrien

+0

@Adrien: Para matrices grandes, tiene razón en que probablemente sea más rápido calcular valores multiplicando sucesivamente por el valor base. Para matrices relativamente pequeñas, como el ejemplo aquí, parece una compensación razonable ir con algo fácil de leer y entender, pero un poco menos eficiente. ;) – gnovice

+0

Me gusta este método ... En mi programación real, creo 10000 por 10000. Así que tal vez debería usar los enfoques más eficientes. Bueno saber de esta manera sin embargo. ¡Gracias! – alext87

6

Suena como una matriz Vandermonde. Así que use vander:

A = vander(1:100); 
A = A(1:10, :); 
+0

El único problema es que VANDER crea matrices cuadradas, por lo que hace un poco de trabajo extra. – gnovice

+0

@gnovice: No es un problema muy difícil de solucionar, vea el código anterior. –

+0

En realidad, dado que OP mencionó el trabajo con matrices cuadradas en un comentario, esta función parece una buena opción. El único cambio que tendría que hacer sería rotarlo usando [ROT90] (http://www.mathworks.com/help/techdoc/ref/rot90.html) para que la columna 'i' contenga poderes de' i ':' A = rot90 (vander (1: N)); ' – gnovice

1

¿Por qué no utilizar un bucle fácil de entender?

c = [1:10]'; %count to 100 for full scale problem 
for i = 1:4; %loop to 10 for full scale problem 
    M(:,i) = c.^(i-1) 
end 

Se necesita más reflexión para comprender las versiones vectorizadas inteligentes de este código que las personas han mostrado. El mío es más una forma bárbara de hacer las cosas, pero cualquiera que lo lea lo entenderá.

Prefiero el código fácil de entender.

(sí, podría haber pre-asignado. No vale la pena la claridad bajado para las pequeñas casos como este.)

+2

Si va por un bucle, debe llenar la matriz línea por línea y no usar el operador. ^. En su lugar, rellene la primera línea con unos y luego cree cada nueva línea multiplicando la anterior por '[1: 100]'. Tienes tanto legibilidad y eficiencia. – Adrien

+2

La sugerencia de Adrien produce un aumento de velocidad del 12%. Para la escala del problema que se discute aquí, fue imperceptible. Tuve que correr esto 100,000 veces para que todo diera 2,8 vs 2,5 segundos. Para mí, mi versión es más sencilla de leer, ya que no hay un paso de iniciación para M, ¡pero no hay que tener en cuenta el gusto! :) – MatlabDoug

Cuestiones relacionadas