Derivado en el borde


9

Mi forma preferida de aproximar una derivada es la diferencia central, es más precisa que la diferencia hacia adelante o hacia atrás, y soy demasiado vago para ir en orden superior. Pero la diferencia central requiere un punto de datos a cada lado del punto que está evaluando. Normalmente esto significa que terminas sin tener una derivada en ninguno de los puntos finales. Para resolverlo, quiero que cambies a la diferencia hacia adelante y hacia atrás en los bordes:

Específicamente, quiero que use una diferencia hacia adelante para el primer punto, una diferencia hacia atrás para el último punto y una diferencia central para todos los puntos en el medio. Además, puede suponer que los valores de x están espaciados uniformemente y centrarse solo en y. Usa estas fórmulas:

ingrese la descripción de la imagen aquí

¡Buena suerte, estoy deseando ver si a alguien se le ocurre una regla simple que reproduzca los 3 derivados en los lugares correctos!

ENTRADA EX:

0.034  9.62    8.885   3.477   2.38

Usaré FD, CD y BD para denotar qué algoritmo usar en qué punto, por lo que se usan más de 5 puntos para aproximar derivados usando

FD     CD      CD      CD     BD

Y luego los valores calculados serían:

9.586  4.4255 -3.0715 -3.2525 -1.097 

Puede suponer que siempre habrá al menos 3 puntos de entrada, y puede calcular con precisión simple o doble.

Y como siempre, gana la respuesta más corta.


3
Solo un punto crítico, las diferencias centrales / hacia adelante / hacia atrás son solo aproximaciones de derivados en un punto, no las derivadas en sí mismas.
Liam

No entiendo a qué corresponde cada número de entrada y salida.
xnor

@xnor, pongo una breve descripción entre la entrada y la salida explicando qué algoritmo usar para qué punto de datos. ¿Tiene sentido ahora?
Tony Ruth

Sí, creo que tiene sentido. Para 5 entradas, lo harías [a,b,c,d,e] -> [b-a,(c-a)/2,(d-b)/2,(e-c)/2,e-d]. ¿Puede haber menos de 3 puntos de entrada?
xnor

@xnor, eso es correcto. Y actualicé para que pueda asumir al menos 3 puntos de entrada.
Tony Ruth

Respuestas:


4

Jalea , 13 10 bytes

I.ịṚjI+2\H

Pruébalo en línea!

Cómo funciona

I.ịṚjI+2\H  Main link. Argument: A (array)

I           Increments; compute the deltas of consecutive values.
            For [a, b, c, d, e], this yields [b-a, c-b, d-c, e-d].
 .ị         At-index 0.5; get the the last and first element.
            This yields [e-d, b-a].
   Ṛ        Reverse the pair.
            This yields [b-a, e-d].
    jI      Join, separating by the increments.
            This yields [b-a, b-a, c-b, d-c, e-d, e-d].
      +2\   Add the values of all overlapping pairs.
            This yields [2(b-a), c-a, d-b, e-c, 2(e-d)].
         H  Halve all resulting numbers.
            This yields [b-a, (c-a)/2, (d-b)/2, (e-c)/2, e-d]. 

3

MATL, 21 15 bytes

2/d1)6Mh8Mt0)h+

TryItOnline

Mitades el vector de entrada, y lleva a diferencias sucesivas, para dar d=[i(2)-i(1) i(3)-i(2) ... i(end)-i(end-1)]/2y luego hace dos vectores modificados, [d(1) d]y [d d(end)], y los añade.

La versión anterior era mejor (por convolución), pero 21 bytes

d1j)6M1)6MTT2/H3$Y+bv

1
Ya veo, bastante inteligente. Entonces, toma una lista de diferencias hacia adelante y una lista de diferencias hacia atrás y las promedia para obtener la diferencia central. Luego, los puntos finales se fijan promediando 2 diferencias hacia adelante o 2 diferencias hacia atrás (en el mismo lugar). Dado que la diferencia hacia adelante y hacia atrás solo se desplaza entre sí en un punto, puede reutilizar mucha estructura.
Tony Ruth

Solo reenvíe las diferencias, de lo contrario sí. Hacer (y(i)-y(i-1))+(y(i+1)-y(i))da y(i+1)-y(i-1), que es el doble de la diferencia centrada.
David


1

05AB1E, 20 19 17 14 bytes

¥Ð¦øO;s¤s0èŠ)˜

Explicado

¥Ð              # triplicate deltas of list
                  [9.585999999999999, -0.7349999999999994, -5.4079999999999995, -1.097]
  ¦øO;          # get central difference (fold addition over deltas and divide by 2)
                  [4.4254999999999995, -3.0714999999999995, -3.2524999999999995]
      s¤        # get backwards difference
                  -1.097
        s0è     # get forwards difference
                  9.585999999999999
           Š)˜  # reorder differences, merge to list and flatten
                  [9.585999999999999, 4.4254999999999995, -3.0714999999999995, -3.2524999999999995, -1.097]

Pruébalo en línea

Guardado 2 bytes gracias a @Adnan



1

Pyth, 14 bytes

.OM>L2._seB-Vt

Pruébelo en línea: demostración

Explicación:

.OM>L2._seB-VtQQ   implicitly add two Qs (input arrays) at the end
           -VtQQ   get all neighbored differences
        seB        get the last element of ^ and append it to ^
      ._           compute all prefixes
   >L2             reduce all prefixes to the last two elements
.OM                compute the average of each ^

1

J, 21 bytes

[:((,{:)+{.,])2-~/\-:

Similar al enfoque utilizado en la solución de @ David .

Uso

   f =: [:((,{:)+{.,])2-~/\-:
   f 0.034 9.62 8.885 3.477 2.38
9.586 4.4255 _3.0715 _3.2525 _1.097

Explicación

[:((,{:)+{.,])2-~/\-:  Input: list A
                   -:  Halve each value in A
              2   \    Select each overlapping sublist of size 2 in A
               -~/     Reduce it using subtraction to get the difference
[:(          )         Operate on the list of differences, call it D
            ]          Identity function, returns D
         {.            Get the head of D
           ,           Join them to get [head(D), D]
   ( {:)               Get the tail of D
    ,                  Join them to get [D, tail(D)]
        +              Add them together elementwise to get the derivatives and return


0

JavaScript (ES6), 62 bytes

a=>a.map((_,i)=>i&&i--<a.length-2?(a[i+2]-a[i])/2:a[i+1]-a[i])

0

Pyth, 27 24 23 21 bytes

.bcF_-VNYK ++] hJ, VUQQJ] eJttK 
.bcF-VYN +] hJ, VQUQJ + tJ] eJ 
++ hJ-V + tQeQ + hQQcR2PtJeJ
 * V ++ 1 *]. 5ttlQ1-V + tQeQ + h
* V ++ 1m.5ttQ1-V + tQeQ + h

Pruébalo en línea!

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.