Arrays (Matriz) multidimensional

07/07/2003 - 11:14 por LEspinosa | Informe spam
Hola a todos:

En una función , uno de los parámetros que le paso, es una matriz dinámica
multidimensional; el problema surge cuando intento recorrer esa matriz, pues
aunque puedo hallar dentro del procedimiento cuantas dimensiones tiene
usando UBound y control de errores, no se me ocurre como puedo recorrer
dicha matriz y extraer sus datos, pues como he dicho anteriormente
desconozco de antemano (en tiempo de compilación) el número de dimensiones
de dicha matriz.
Ese parámetro que paso, la matriz, lo impone la interfaz, por lo que no
puedo modificarlo por una colección de clases, por ejemplo.


¿Alguna idea o sugerencia?


Gracias a todos de antemano.
Leonardo Espinosa

Preguntas similare

Leer las respuestas

#6 LEspinosa
08/07/2003 - 11:42 | Informe spam
Hola Javier:

Concretamente estoy inmerso en una aplicación OLAP, con bases de datos
multidimensionales, orientado al mundo financiero. En este campo la
capacidad de análisis está en relación directa con el número de dimensiones
y... no me enrollo más, pero aunque es dificil que alcance las 50 o más
dimensiones (que no creo) es habitual que tenga entre 5 y 15 dimensiones.
La necesidad de no limitar excesivamente este análisis responde al guión,
pues una de las exigencias del proyecto es evitar precisamente esto y no
querían presentar la aplicación diciendo que estaba limitado a 10 o 12
dimensiones.
Además si haces pruebas de tiempo verás el aumento enorme de rendimiento de
este método.

En cuanto al error que me dices, no lo he detectado aún (y espero no
encontrarmelo ;-) ), pero me suena que está relacionado con el
bloqueo/desbloqueo de la matriz (ver tipo de datos SAFEARRAY en MSDN y
http://www.buygold.net/v01n07/v01n07.html).
Un error similar me ocurrió con la técnica tradicional de tratamiento de
arrays y lo resolvimos usando control de errores.

Por si te interesa te pego algunas de las fuentes de dónde he tomado la
idea:
'Write Faster Apps with VB Pointers' en
http://archive.devx.com/premier/mgz...mc1097.pdf
Hardcore Visual Basic de Bruce McKinney en MSDN (el libro en español:
Microsoft Visual Basic Avanzado)

Saludos
Leonardo Espinosa


"Javier Balkenende" escribió en el mensaje
news:OgU20#
Hola Leonardo:

Muy bueno.
Hice unas pruebas y varias veces me funcionó bien, pero sin haber


modificado
nada luego lo probé de nuevo y me cerró el IDE. El error me dio luego de
ejecutar varias veces la rutina (tal vez hice algo mal, aunque no creo).

También tengo una curiosidad ¿En qué tipo de proyecto se puede usar una
matriz de 50 dimensiones, qué podría necesitar eso?

Saludos,
Javier



"LEspinosa" escribió en el mensaje
news:%23c$
> En primer lugar gracias por vuestras respuestas, gracias Javier y


Victor.
> Pero vereis, el código que me pasaste Javier no me satisfacía
completamente,
> pues me limitaba el número de dimensiones, o mejor dicho, si quería usar
más
> de 50 dimensiones por ejemplo, el select case que tenía que construir


era
> enorme, así que seguí buscando, y recordé la función VarPtr y


VarPtrArray
> (HOWTO: Get the Address of Variables in Visual Basic - Knowledge Base
> 199824).
> Utilicé la estructura SAFEARRAY y CopyMemory, para utilizar punteros y
> demás.
> Así que pegando piezas de aquí y de allá, un poco de sal, pimienta y
> probando diversas combinaciones... obtuve el siguiente resultado que a
> continuación pego por si os vale:
>
>
>
> En las declaraciones de un modulo:
>
> Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Dest
As
> Any, Source As Any, ByVal Length As Long)
> Public Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr"
(Ptr()
> As Any) As Long
>
> Public Type SAFEARRAYBOUND
> cElements As Long
> lLbound As Long
> End Type
>
> Public Type SAFEARRAY1D
> cDims As Integer
> fFeatures As Integer
> cbElements As Long
> cLocks As Long
> pvData As Long
> Bounds(0 To 0) As SAFEARRAYBOUND
> End Type
>
> Public Type SAFEARRAY100D
> cDims As Integer
> fFeatures As Integer
> cbElements As Long
> cLocks As Long
> pvData As Long
> 'Este dato hace que el límite de dimensiones esté ahora en 100
> Bounds(0 To 99) As SAFEARRAYBOUND
> End Type
>
>
> En mi función de ese módulo:
>
> Public Function MiFunciónArray(ByRef anDiasRotacion() As Long) As Double
>
> Dim SA As SAFEARRAY100D, saTemp As SAFEARRAY1D
> Dim lngSafeArray As Long
> Dim cDims As Integer
> Dim i As Long, numElems As Long
>
> 'recuperamos informacion de las dimensiones de la matriz y número de
> elementos
> CopyMemory lngSafeArray, ByVal VarPtrArray(anDiasRotacion), 4
> CopyMemory cDims, ByVal lngSafeArray, Len(cDims)
> CopyMemory SA, ByVal lngSafeArray, Len(SA) - 8 * (100 - cDims)
>
> numElems = 1
> For i = 0 To SA.cDims - 1
> numElems = numElems * SA.Bounds(i).cElements
> Next i
>
> 'Creamos una matriz temporal unidimensional y recuperamos su
estructura
> SAFEARRAY1D
> ReDim aTemp(0) As Long
> CopyMemory lngSafeArray, ByVal VarPtrArray(aTemp), 4
> CopyMemory saTemp, ByVal lngSafeArray, Len(saTemp)
>
> 'Modifica el número de elementos y apunta a los datos
> saTemp.pvData = SA.pvData
> saTemp.Bounds(0).cElements = numElems
> CopyMemory ByVal VarPtrArray(aTemp), VarPtr(saTemp), 4
>
> 'Y de esta forma ya tengo todos los datos en una matriz


unidimensional
> For i = 0 To UBound(aTemp)
> Debug.Print aTemp(i)
> Next i
>
> Me parece que con una pequeña modificación de este algoritmo se podrían
> manejar bitmaps con mucha mayor rapidez y rendimiento que usando los for
> next.
>
> Saludos
> Leonardo Espinosa
>
>
> "LEspinosa" escribió en el mensaje
> news:OIm$
> > Hola a todos:
> >
> > En una función , uno de los parámetros que le paso, es una matriz
dinámica
> > multidimensional; el problema surge cuando intento recorrer esa


matriz,
> pues
> > aunque puedo hallar dentro del procedimiento cuantas dimensiones tiene
> > usando UBound y control de errores, no se me ocurre como puedo


recorrer
> > dicha matriz y extraer sus datos, pues como he dicho anteriormente
> > desconozco de antemano (en tiempo de compilación) el número de
dimensiones
> > de dicha matriz.
> > Ese parámetro que paso, la matriz, lo impone la interfaz, por lo que


no
> > puedo modificarlo por una colección de clases, por ejemplo.
> >
> >
> > ¿Alguna idea o sugerencia?
> >
> >
> > Gracias a todos de antemano.
> > Leonardo Espinosa
> >
> >
> >
>
>



Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.493 / Virus Database: 292 - Release Date: 25/06/2003


Respuesta Responder a este mensaje
#7 Javier Balkenende
08/07/2003 - 13:06 | Informe spam
Creo que voy a tener que estudiar C, de manera que esté más familiarizado
con el manejo de punteros, cuando se quiere hacer cosas que VB no hace a
veces es necesario ir a un manejo de bajo nivel.
Gracias por la información.
Saludos,

Javier

"LEspinosa" escribió en el mensaje
news:
Hola Javier:

Concretamente estoy inmerso en una aplicación OLAP, con bases de datos
multidimensionales, orientado al mundo financiero. En este campo la
capacidad de análisis está en relación directa con el número de


dimensiones
y... no me enrollo más, pero aunque es dificil que alcance las 50 o más
dimensiones (que no creo) es habitual que tenga entre 5 y 15 dimensiones.
La necesidad de no limitar excesivamente este análisis responde al guión,
pues una de las exigencias del proyecto es evitar precisamente esto y no
querían presentar la aplicación diciendo que estaba limitado a 10 o 12
dimensiones.
Además si haces pruebas de tiempo verás el aumento enorme de rendimiento


de
este método.

En cuanto al error que me dices, no lo he detectado aún (y espero no
encontrarmelo ;-) ), pero me suena que está relacionado con el
bloqueo/desbloqueo de la matriz (ver tipo de datos SAFEARRAY en MSDN y
http://www.buygold.net/v01n07/v01n07.html).
Un error similar me ocurrió con la técnica tradicional de tratamiento de
arrays y lo resolvimos usando control de errores.

Por si te interesa te pego algunas de las fuentes de dónde he tomado la
idea:
'Write Faster Apps with VB Pointers' en
http://archive.devx.com/premier/mgz...mc1097.pdf
Hardcore Visual Basic de Bruce McKinney en MSDN (el libro en español:
Microsoft Visual Basic Avanzado)

Saludos
Leonardo Espinosa


"Javier Balkenende" escribió en el mensaje
news:OgU20#
> Hola Leonardo:
>
> Muy bueno.
> Hice unas pruebas y varias veces me funcionó bien, pero sin haber
modificado
> nada luego lo probé de nuevo y me cerró el IDE. El error me dio luego de
> ejecutar varias veces la rutina (tal vez hice algo mal, aunque no creo).
>
> También tengo una curiosidad ¿En qué tipo de proyecto se puede usar una
> matriz de 50 dimensiones, qué podría necesitar eso?
>
> Saludos,
> Javier
>
>
>
> "LEspinosa" escribió en el mensaje
> news:%23c$
> > En primer lugar gracias por vuestras respuestas, gracias Javier y
Victor.
> > Pero vereis, el código que me pasaste Javier no me satisfacía
> completamente,
> > pues me limitaba el número de dimensiones, o mejor dicho, si quería


usar
> más
> > de 50 dimensiones por ejemplo, el select case que tenía que construir
era
> > enorme, así que seguí buscando, y recordé la función VarPtr y
VarPtrArray
> > (HOWTO: Get the Address of Variables in Visual Basic - Knowledge Base
> > 199824).
> > Utilicé la estructura SAFEARRAY y CopyMemory, para utilizar punteros y
> > demás.
> > Así que pegando piezas de aquí y de allá, un poco de sal, pimienta y
> > probando diversas combinaciones... obtuve el siguiente resultado que a
> > continuación pego por si os vale:
> >
> >
> >
> > En las declaraciones de un modulo:
> >
> > Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory"


(Dest
> As
> > Any, Source As Any, ByVal Length As Long)
> > Public Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr"
> (Ptr()
> > As Any) As Long
> >
> > Public Type SAFEARRAYBOUND
> > cElements As Long
> > lLbound As Long
> > End Type
> >
> > Public Type SAFEARRAY1D
> > cDims As Integer
> > fFeatures As Integer
> > cbElements As Long
> > cLocks As Long
> > pvData As Long
> > Bounds(0 To 0) As SAFEARRAYBOUND
> > End Type
> >
> > Public Type SAFEARRAY100D
> > cDims As Integer
> > fFeatures As Integer
> > cbElements As Long
> > cLocks As Long
> > pvData As Long
> > 'Este dato hace que el límite de dimensiones esté ahora en 100
> > Bounds(0 To 99) As SAFEARRAYBOUND
> > End Type
> >
> >
> > En mi función de ese módulo:
> >
> > Public Function MiFunciónArray(ByRef anDiasRotacion() As Long) As


Double
> >
> > Dim SA As SAFEARRAY100D, saTemp As SAFEARRAY1D
> > Dim lngSafeArray As Long
> > Dim cDims As Integer
> > Dim i As Long, numElems As Long
> >
> > 'recuperamos informacion de las dimensiones de la matriz y número


de
> > elementos
> > CopyMemory lngSafeArray, ByVal VarPtrArray(anDiasRotacion), 4
> > CopyMemory cDims, ByVal lngSafeArray, Len(cDims)
> > CopyMemory SA, ByVal lngSafeArray, Len(SA) - 8 * (100 - cDims)
> >
> > numElems = 1
> > For i = 0 To SA.cDims - 1
> > numElems = numElems * SA.Bounds(i).cElements
> > Next i
> >
> > 'Creamos una matriz temporal unidimensional y recuperamos su
> estructura
> > SAFEARRAY1D
> > ReDim aTemp(0) As Long
> > CopyMemory lngSafeArray, ByVal VarPtrArray(aTemp), 4
> > CopyMemory saTemp, ByVal lngSafeArray, Len(saTemp)
> >
> > 'Modifica el número de elementos y apunta a los datos
> > saTemp.pvData = SA.pvData
> > saTemp.Bounds(0).cElements = numElems
> > CopyMemory ByVal VarPtrArray(aTemp), VarPtr(saTemp), 4
> >
> > 'Y de esta forma ya tengo todos los datos en una matriz
unidimensional
> > For i = 0 To UBound(aTemp)
> > Debug.Print aTemp(i)
> > Next i
> >
> > Me parece que con una pequeña modificación de este algoritmo se


podrían
> > manejar bitmaps con mucha mayor rapidez y rendimiento que usando los


for
> > next.
> >
> > Saludos
> > Leonardo Espinosa
> >
> >
> > "LEspinosa" escribió en el mensaje
> > news:OIm$
> > > Hola a todos:
> > >
> > > En una función , uno de los parámetros que le paso, es una matriz
> dinámica
> > > multidimensional; el problema surge cuando intento recorrer esa
matriz,
> > pues
> > > aunque puedo hallar dentro del procedimiento cuantas dimensiones


tiene
> > > usando UBound y control de errores, no se me ocurre como puedo
recorrer
> > > dicha matriz y extraer sus datos, pues como he dicho anteriormente
> > > desconozco de antemano (en tiempo de compilación) el número de
> dimensiones
> > > de dicha matriz.
> > > Ese parámetro que paso, la matriz, lo impone la interfaz, por lo que
no
> > > puedo modificarlo por una colección de clases, por ejemplo.
> > >
> > >
> > > ¿Alguna idea o sugerencia?
> > >
> > >
> > > Gracias a todos de antemano.
> > > Leonardo Espinosa
> > >
> > >
> > >
> >
> >
>
>
>
> Outgoing mail is certified Virus Free.
> Checked by AVG anti-virus system (http://www.grisoft.com).
> Version: 6.0.493 / Virus Database: 292 - Release Date: 25/06/2003
>
>







Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.493 / Virus Database: 292 - Release Date: 25/06/2003
email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una pregunta AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida