Portal    Foro    Buscar    FAQ    Registrarse    Conectarse


Publicar nuevo tema  Responder al tema 
Página 2 de 2
Ir a la página Anterior  1, 2
 
Interpolación
Autor Mensaje
Responder citando   Descargar mensaje  
Mensaje Cómo Buscar Datos 
 
En primer lugar, disculparme por el tiempo que he estado sin cumplir con lo prometido.

Para emplear las funciones anteriores se precisan tablas que contengan valores próximos al buscado. Pero normalmente estas tablas están integradas en otras mayores, por lo que hay que hacer «minería» de datos. En el siguiente ejemplo se muestra el valor a buscar y los datos próximos:

    X0=    7,0
        
Índice    X    Y
0            1,1    9,01
1            1,7    8,55
2            2,0    8,34
3            2,1    8,27
4            3,2    7,60
5            3,7    7,35
6            4,0    7,22
7            4,6    7,01
8            5,1    6,85
9            5,5    6,78
10          6,2    6,74
11         6,8    6,82
12         7,9    7,31
13            8,5    7,80

14            9,9    9,80
15          10,8    11,87

Los datos marcados en azul son los que deberíamos emplear como argumentos de nuestra función.
Para ello, los tenemos que buscar dentro de la tabla a partir de la «X0» marcada. ¿Cómo? Existen dos posibilidades:
La primera, a lo «burro», buscando secuencialmente desde el principio para dar con el valor adecuado.
La segunda consiste en ir empleando el método de bisección —empleado para resolución de ecuaciones— a la tabla.
Se comienza comprobando que X0 no está fuera de la tabla, esto es, que no es menor que el primer número —recuérdese que la tabla tiene que estar ordenada— ni mayor que el último; en nuestro caso 1,1<=7<=10,8. En caso de querer extrapolar se tomarían los valores extremos más cercano a la X0
Luego se toma como A el índice mínimo (0), como B el máximo (15) y como C el intermedio (7)
Se comprueba en que intervalo está nuestro objetivo y se ve que X(7)<X0<X(15), por tanto, ahora la A será la C anterior, esto es 7, la B se mantiene en 15, y la C vuelve a ser la intermedia, 11.
Se repite el proceso hasta que B-A=1. Siempre hay que comprobar que el número buscado no coincide con uno de los marcados por los índices; en caso de ocurrir esa coincidencia no es necesario interpolar, sino que basta con devolver el dato de la tabla.
En ese momento, A y B son los índices que «rodean» al valor buscado. Si queremos una interpolación lineal ya habríamos acabado. Si queremos una cúbica, habría que devolver los datos A-1, A, B, B+1 —el ejemplo— y así sucesivamente.
Sólo nos queda resolver el caso de los extremos. Imaginemos en nuestro caso que A=14 y B=15 y estamos empleando una interpolación cúbica. En tal caso hay dos posibilidades. La primera es considerar que si se está en un extremo, tomar todos esos valores, esto es de 12 a 15. Pero como al aumentar el grado de interpolación pueden aparecer errores grandes en los extremos, otra opción consiste en realizar una interpolación par del grado mayor posible, en este caso, tomar los datos 13 a 15 y realizar la interpolación cuadrática.
En el código siguiente —que funciona, pero no esta optimado; aún estoy trabajando en él, especialmente en la interpolación par en los extremos y en sacar las tablas para generalizarla— realiza la función descrita, pero ampliada a dos variables. —He dejado las tablas originales por claridad, aunque se alargue mucho el código.—

PS.- Evidentemente, en una tabla de hasta ocho datos se necesitan tres iteraciones, de hasta dieciséis cuatro ... de hasta 65536 dieciséis interaciones...
PPS.- La función devuelve un valor booleano, siendo el resultado False si no se encontró un resultado válido o True si las matrices X, Y, y Z tienen valores válidos. Se podría hacer con una función que de como resultado una Struc definida por el usuario, pero ¡qué pereza!

 



 
última edición por Grandamakulo el Viernes, 21 Octobre 2016, 10:36; editado 3 veces 
Grandamakulo - Ver perfil del usuarioEnviar mensaje privadoVisitar sitio web del usuario 
Volver arribaPágina inferior
Responder citando   Descargar mensaje  
Mensaje Re: Interpolación 
 
Public Function BuscaValores(dblX As Float, dblY As Float, dblXR As Float[], dblYR As Float[], dblZR As Float[]) As Boolean
        ' **** Busca datos en tablas en dos dimensiones.
        ' <<<<Devuelve>>>>
        '       dblX:   Valor "X" para el que buscar la "Z"
        '       dblY:   Valor "Y" para el que buscar la "Z"
        ' TODO:
        '     - Sacar tablas para generalizar
        '     - Interpolación par n-1 en los extremos
        
        
    Dim iG As Integer
    Dim dblXl As New Float[8]
    Dim dblYl As New Float[24]
    Dim dblZl As New Float[8, 24]
    Dim XA As Integer
    Dim XB As Integer
    Dim YA As Integer
    Dim YB As Integer
    Dim C As Integer
    Dim i As Integer
    Dim j As Integer
        
    iG = dblXR.Count - 1
    
    dblXl[0] = -0.225483034
    dblXl[1] = 0.556302501
    dblXl[2] = 0.985875357
    dblXl[3] = 1.260071388
    dblXl[4] = 1.741939078
    dblXl[5] = 2.08278537
    dblXl[6] = 2.556302501
    dblXl[7] = 3.0
    
    dblYl[0] = 4.0
    dblYl[1] = 5.0
    dblYl[2] = 6.0
    dblYl[3] = 7.0
    dblYl[4] = 8.0
    dblYl[5] = 9.0
    dblYl[6] = 10.0
    dblYl[7] = 11.0
    dblYl[8] = 12.0
    dblYl[9] = 13.0
    dblYl[10] = 14.0
    dblYl[11] = 15.0
    dblYl[12] = 16.0
    dblYl[13] = 17.0
    dblYl[14] = 18.0
    dblYl[15] = 19.0
    dblYl[16] = 20.0
    dblYl[17] = 21.0
    dblYl[18] = 22.0
    dblYl[19] = 23.0
    dblYl[20] = 24.0
    dblYl[21] = 25.0
    dblYl[22] = 26.0
    dblYl[23] = 27.0

    If (dblX <dblXl> dblXl[7] Or dblY <dblYl> dblYl[23]) Then Return False

    dblZl[0, 0] = -0.3769
     dblZl[1, 0] = -1.8064
     dblZl[2, 0] = -2.3368
     dblZl[3, 0] = -2.4601
     dblZl[4, 0] = -2.5469
     dblZl[5, 0] = -2.561
     dblZl[6, 0] = -2.566
     dblZl[0, 1] = -0.3315
     dblZl[1, 1] = -1.7747
     dblZl[2, 1] = -2.3337
     dblZl[3, 1] = -2.4608
     dblZl[4, 1] = -2.5465
     dblZl[5, 1] = -2.5607
     dblZl[6, 1] = -2.5658
     dblZl[0, 2] = -0.2682
     dblZl[1, 2] = -1.7345
     dblZl[2, 2] = -2.331
     dblZl[3, 2] = -2.4605
     dblZl[4, 2] = -2.5467
     dblZl[5, 2] = -2.5608
     dblZl[6, 2] = -2.5658
     dblZl[0, 3] = -0.1982
     dblZl[1, 3] = -1.6851
     dblZl[2, 3] = -2.314
     dblZl[3, 3] = -2.4572
     dblZl[4, 3] = -2.5481
     dblZl[5, 3] = -2.5615
     dblZl[6, 3] = -2.5665
     dblZl[0, 4] = -0.1238
     dblZl[1, 4] = -1.6252
     dblZl[2, 4] = -2.2791
     dblZl[3, 4] = -2.4462
     dblZl[4, 4] = -2.5463
     dblZl[5, 4] = -2.5597
     dblZl[6, 4] = -2.5646
     dblZl[0, 5] = -0.0424
     dblZl[1, 5] = -1.5529
     dblZl[2, 5] = -2.2297
     dblZl[3, 5] = -2.4214
     dblZl[4, 5] = -2.5343
     dblZl[5, 5] = -2.5501
     dblZl[6, 5] = -2.552
     dblZl[0, 6] = 0.0498
     dblZl[1, 6] = -1.4655
     dblZl[2, 6] = -2.1659
     dblZl[3, 6] = -2.3763
     dblZl[4, 6] = -2.5047
     dblZl[5, 6] = -2.5269
     dblZl[6, 6] = -2.5333
     dblZl[0, 7] = 0.1596
     dblZl[1, 7] = -1.3581
     dblZl[2, 7] = -2.081
     dblZl[3, 7] = -2.3036
     dblZl[4, 7] = -2.4499
     dblZl[5, 7] = -2.4823
     dblZl[6, 7] = -2.4937
     dblZl[0, 8] = 0.2934
     dblZl[1, 8] = -1.2256
     dblZl[2, 8] = -1.9674
     dblZl[3, 8] = -2.1965
     dblZl[4, 8] = -2.3631
     dblZl[5, 8] = -2.4092
     dblZl[6, 8] = -2.4318
     dblZl[0, 9] = 0.4557
     dblZl[1, 9] = -1.0673
     dblZl[2, 9] = -1.8186
     dblZl[3, 9] = -2.0531
     dblZl[4, 9] = -2.2445
     dblZl[5, 9] = -2.3083
     dblZl[6, 9] = -2.3491
     dblZl[0, 10] = 0.65
     dblZl[1, 10] = -0.8841
     dblZl[2, 10] = -1.6292
     dblZl[3, 10] = -1.8741
     dblZl[4, 10] = -2.0989
     dblZl[5, 10] = -2.1848
     dblZl[6, 10] = -2.2505
     dblZl[0, 11] = 0.8808
     dblZl[1, 11] = -0.6687
     dblZl[2, 11] = -1.3967
     dblZl[3, 11] = -1.6611
     dblZl[4, 11] = -1.9284
     dblZl[5, 11] = -2.0411
     dblZl[6, 11] = -2.1375
     dblZl[0, 12] = 1.1558
     dblZl[1, 12] = -0.3952
     dblZl[2, 12] = -1.1264
     dblZl[3, 12] = -1.4176
     dblZl[4, 12] = -1.73
     dblZl[5, 12] = -1.8727
     dblZl[6, 12] = -2.0034
     dblZl[0, 13] = 1.4822
     dblZl[1, 13] = -0.0419
     dblZl[2, 13] = -0.8243
     dblZl[3, 13] = -1.1475
     dblZl[4, 13] = -1.5021
     dblZl[5, 13] = -1.6768
     dblZl[6, 13] = -1.842
     dblZl[0, 14] = 1.8559
     dblZl[1, 14] = 0.3458
     dblZl[2, 14] = -0.4924
     dblZl[3, 14] = -0.8561
     dblZl[4, 14] = -1.2661
     dblZl[5, 14] = -1.4721
     dblZl[6, 14] = -1.6624
     dblZl[0, 15] = 2.2669
     dblZl[1, 15] = 0.696
     dblZl[2, 15] = -0.1315
     dblZl[3, 15] = -0.551
     dblZl[4, 15] = -1.0562
     dblZl[5, 15] = -1.2892
     dblZl[6, 15] = -1.4827
     dblZl[0, 16] = 2.676
     dblZl[1, 16] = 1.088
     dblZl[2, 16] = 0.206
     dblZl[3, 16] = -0.321
     dblZl[4, 16] = -0.88
     dblZl[5, 16] = -1.137
     dblZl[6, 16] = -1.362
     dblZl[0, 17] = 2.7766
     dblZl[1, 17] = 1.2065
     dblZl[2, 17] = 0.3467
     dblZl[3, 17] = -0.1377
     dblZl[4, 17] = -0.7361
     dblZl[5, 17] = -0.9964
     dblZl[6, 17] = -1.2439
     dblZl[0, 18] = 2.9304
     dblZl[1, 18] = 1.3821
     dblZl[2, 18] = 0.5353
     dblZl[3, 18] = 0.0328
     dblZl[4, 18] = -0.5605
     dblZl[5, 18] = -0.8606
     dblZl[6, 18] = -1.1187
     dblZl[0, 19] = 3.1634
     dblZl[1, 19] = 1.6107
     dblZl[2, 19] = 0.7708
     dblZl[3, 19] = 0.2531
     dblZl[4, 19] = -0.3895
     dblZl[5, 19] = -0.703
     dblZl[6, 19] = -0.9681
     dblZl[0, 20] = 3.4643
     dblZl[1, 20] = 1.9034
     dblZl[2, 20] = 1.0338
     dblZl[3, 20] = 0.4943
     dblZl[4, 20] = -0.2033
     dblZl[5, 20] = -0.5259
     dblZl[6, 20] = -0.8288
     dblZl[0, 21] = 3.8211
     dblZl[1, 21] = 2.2564
     dblZl[2, 21] = 1.3265
     dblZl[3, 21] = 0.7605
     dblZl[4, 21] = 0.0172
     dblZl[5, 21] = -0.2992
     dblZl[6, 21] = -0.6394
     dblZl[0, 22] = 4.221
     dblZl[1, 22] = 2.632
     dblZl[2, 22] = 1.699
     dblZl[3, 22] = 1.132
     dblZl[4, 22] = 0.286
     dblZl[5, 22] = -0.051
     dblZl[6, 22] = -0.408
     dblZl[0, 23] = 4.61
     dblZl[1, 23] = 3.066
     dblZl[2, 23] = 2.132
     dblZl[3, 23] = 1.585
     dblZl[4, 23] = 0.652
     dblZl[5, 23] = 0.241
     dblZl[6, 23] = -0.121
    
     dblZl[7, 0] = -2.563
      dblZl[7, 1] = -2.5629
      dblZl[7, 2] = -2.5628
      dblZl[7, 3] = -2.564
      dblZl[7, 4] = -2.562
      dblZl[7, 5] = -2.5432
      dblZl[7, 6] = -2.5264
      dblZl[7, 7] = -2.4866
      dblZl[7, 8] = -2.4311
      dblZl[7, 9] = -2.3621
      dblZl[7, 10] = -2.2838
      dblZl[7, 11] = -2.1961
      dblZl[7, 12] = -2.0902
      dblZl[7, 13] = -1.9559
      dblZl[7, 14] = -1.7901
      dblZl[7, 15] = -1.5953
      dblZl[7, 16] = -1.5032
      dblZl[7, 17] = -1.4156
      dblZl[7, 18] = -1.2767
      dblZl[7, 19] = -1.1266
      dblZl[7, 20] = -1.036
      dblZl[7, 21] = -0.9057
      dblZl[7, 22] = -0.6839
      dblZl[7, 23] = -0.3499
    
'    
     XA = 0
     XB = 7
     C = Int(XA + XB) / 2
     Do
         If dblXl[XA] = dblX Then XB = XA + 1
         If dblXl[XB] = dblX Then XA = XB - 1
         If dblXl[C] = dblX Then
          XA = C
          XB = XA + 1
         End If
         If dblX >= dblXl[C] And dblX <dblXl> dblXl[XA] And dblX <= dblXl[C] Then XB = C
         C = Int(XA + XB) / 2
     Loop Until XA = XB - 1
     If 7 - XA < iG Then
             XA = 4
         Else
          If XA - 1 <0>= dblYl[C] And dblY <dblYl> dblYl[YA] And dblY <= dblYl[C] Then YB = C
        C = Int(YA + YB) / 2
    Loop Until YA = YB - 1
    If 23 - YA < iG Then
            YA = 20
        Else
          If YA - 1 < 0 Then
            YA = 0
          Else
            YA = YA - 1
          End If
    End If
    YB = YA + iG

    For i = 0 To iG
        dblXR[i] = dblXl[XA + i]
        dblYR[i] = dblYl[YA + i]
        For j = 0 To iG
            dblZR[i, j] = dblZl[XA + i, YA + j]
        Next
    Next
    Return True
    
End Function

 



 
Grandamakulo - Ver perfil del usuarioEnviar mensaje privadoVisitar sitio web del usuario 
Volver arribaPágina inferior
Responder citando   Descargar mensaje  
Mensaje Re: Interpolación 
 
Ahora voy a añadir otro método de interpolación. Y entonces surge la preguna: ¿es necesario otro método? Si, como ya se dijo, existe un único polinomio que pase por un determinado conjunto de puntos, o lo que es lo mismo, usemos el método que usemos siempre tendremos la misma solución; cojamos el más rápido, y listo. Efectivamente, el de Lagrange es el más rápido y ya está implementado. Punto.
Pero, ¿y si los puntos fuesen equidistantes, cosa que pasa a menudo?, ¿podríamos buscar un método aún más rápido?
Pues sí. Existe un método parecido al de Lagrange, que es el de las diferencias finitas. Este método es más lento pero en el caso que comentamos, esto es, cuando los intervalos son constantes, es bastante fácil de simplificar y da, como veremos, un método más rápido de interpolación. Se trata del método Newton - Gregory —sin negar el genio de ambos, es bastante más que probable que este método ya estuviese desarrollado antes, pero sabemos cómo son los británicos para estas cosas: les falta tiempo para bautizarlas—. En fin, que os dejo el código y un par de comentarios después:

Public Function hNewton(Xl As Float, X As Variant, Ya As Variant) As Float
  ' **** Interpolación de Newton-Gregory -datos equiespaciados- en una sola dimensión.
  ' <<<< Devuelve un valor "Y" correspondiente con la "X" dada dentro de una tabla de valores
  ' >>>>
  '     Xl:  Valor para el que buscar la "Y"
  '     X :   Lista de valores "X" de la tabla
  '     Y :   Lista de valores "Y" de la tabla
  Dim i As Byte         ' Contador
  Dim j As Byte         ' Contador
  Dim iG As Byte        ' Grado del polinomio de interpolación
  Dim DY As New Float[X.Count] 'Diferencias
  Dim Y As New Float[X.Count]
  Dim Sum As Float      ' Sumatorio del polinomio
  Dim Prd As Float      ' Productorio del polinomio
  Dim Delta As Float    ' Separación X
  
  iG = X.Count - 1   ' El grado se corresponde con el tamaño de la tabla - 1
  
  For i = 0 To iG
    DY[i] = Ya[i]
    Y[i] = Ya[i]
  Next
  
  For j = 0 To iG - 1
    For i = j + 1 To iG
      DY[i] = DY[i] - Y[i - 1]
    Next
    For i = j + 1 To iG - 1
      Y[i] = DY[i]
    Next
  Next
  
  Delta = X[1] - X[0]
  Sum = Y[0]
  Prd = 1
  
  For i = 0 To iG - 1
    Prd = Prd * (Xl - X[i]) / Delta / (i + 1)
    Sum = Sum + DY[i + 1] * Prd
  Next
  
  Return Sum

End Function


Al probarla un millón de veces —literalmente— con polinomios cúbicos y comparar con el método de Lagrange, efectivamente es más rápido. El de Lagrange daba un promedio de 13,1s y el de NG en torno a 7,9s, esto es, un ahorro de un 40% de tiempo. NAda espectacular, desde luego. Pero ahí está, por si fuere menester para cualquier cosa.
Eso sí, insistamos en que el método de Lagrange se puede emplear con separación heterogénea de datos, cosa que no sucede con el NG.

Y eso es todo por hoy. Ahora me voy a merendar, ¡qué releñes!, que me lo he ganado.

 



 
Grandamakulo - Ver perfil del usuarioEnviar mensaje privadoVisitar sitio web del usuario 
Volver arribaPágina inferior
Responder citando   Descargar mensaje  
Mensaje Re: Interpolación 
 
Volviendo al tema de los píxeles por estar equiespaciados, se me antoja el método preferido para interpolar sus valores, ¿me equivoco?.

Lo que pasa es que ya está todo inventado y además empaquetado en librerías... pero es muy constructivo saber cómo y por qué funcionan las cosas.

Gracias por tu tiempo, Grandamakulo

Saludos
 




===================
Jesús Guardón

Por favor, usemos el corrector ortográfico antes de pulsar el botón "Enviar".

"uo ǝs ʇɐu pıɟıɔıן ɐdɹǝupǝɹ ɐ dɹoƃɹɐɯɐɹ, soןo ɥɐʎ bnǝ dɹodouǝɹsǝןo"
 
jguardon - Ver perfil del usuarioEnviar mensaje privado 
Volver arribaPágina inferior
Responder citando   Descargar mensaje  
Mensaje Re: Interpolación 
 
Pssssí, la verdad es que hay muchas cosas hechas, peeeeero, además de valer para «saber» cómo funciona, puede ser útil en algún caso.
De hecho, al final de «esto» y antes de comenzar con otra cosa del mismo pelaje, quisiera poner tres ejemplos distintos de cómo se computan determinadas funciones, y de cómo implementar algunas en caso de ser necesario.
Además, hay más aplicaciones que filtros de imágenes para móviles        
También pondré un ejemplo, jajaja —de otro tipo de aplicación—.

 



 
última edición por Grandamakulo el Viernes, 09 Febrero 2018, 23:35; editado 1 vez 
Grandamakulo - Ver perfil del usuarioEnviar mensaje privadoVisitar sitio web del usuario 
Volver arribaPágina inferior
Mostrar mensajes anteriores:    
 
Ocultar¡Este tema fue útil?

 

Elegir valoración:                       

Media de valoración Valoración mínima Valoración máxima Número de valoraciones
7.00 7 7 1
 
OcultarTemas parecidos
Tema Autor Foro Respuestas último mensaje
No hay nuevos mensajes ¿ Existe La Interpolación De Cadenas En ... Shell General 2 Viernes, 19 Julio 2013, 12:33 Ver último mensaje
Shell
 

Publicar nuevo tema  Responder al tema  Página 2 de 2
Ir a la página Anterior  1, 2

Usuarios navegando en este tema: 0 registrados, 0 ocultos y 1 invitado
Usuarios registrados conectados: Ninguno


 
Lista de permisos
No puede crear mensajes
No puede responder temas
No puede editar sus mensajes
No puede borrar sus mensajes
No puede votar en encuestas
No puede adjuntar archivos
No puede descargar archivos
No puede publicar eventos en el calendario