Derivata al limite


9

Il mio modo preferito per approssimare una derivata è la differenza centrale, è più accurata della differenza in avanti o della differenza all'indietro, e sono troppo pigro per passare all'ordine superiore. Ma la differenza centrale richiede un punto dati su entrambi i lati del punto che si sta valutando. Normalmente questo significa che non si ottiene una derivata su entrambi gli endpoint. Per risolverlo, voglio che passi alla differenza avanti e indietro ai bordi:

In particolare, voglio che tu usi una differenza in avanti per il primo punto, una differenza all'indietro per l'ultimo punto e una differenza centrale per tutti i punti nel mezzo. Inoltre, puoi presumere che i valori di x siano equidistanti e che si concentrino solo su y. Usa queste formule:

inserisci qui la descrizione dell'immagine

Buona fortuna, non vedo l'ora di vedere se qualcuno troverà una semplice regola che riproduce tutti e 3 i derivati ​​nei posti giusti!

INGRESSO EX:

0.034  9.62    8.885   3.477   2.38

Userò FD, CD e BD per indicare l'algoritmo da utilizzare in quale punto, quindi sopra i 5 punti vengono usati per approssimare i derivati ​​usando

FD     CD      CD      CD     BD

E quindi i valori calcolati sarebbero:

9.586  4.4255 -3.0715 -3.2525 -1.097 

Puoi presumere che ci saranno sempre almeno 3 punti di input e puoi calcolare usando la precisione singola o doppia.

E come sempre, la risposta più breve vince.


3
Solo un nitpick, le differenze centrali / avanti / indietro sono solo approssimazioni di derivati ​​in un punto, non i derivati ​​stessi.
Liam,

Non capisco a cosa corrisponda ciascun numero di input e output.
xnor

@xnor, ho inserito una breve descrizione tra l'input e l'output che spiega quale algoritmo utilizzare per quale punto dati. Ha senso adesso?
Tony Ruth,

Sì, penso abbia senso. Per 5 input, lo faresti [a,b,c,d,e] -> [b-a,(c-a)/2,(d-b)/2,(e-c)/2,e-d]. Possono esserci meno di 3 punti di input?
xnor

@xnor, esatto. E, ho aggiornato in modo da poter assumere almeno 3 punti di input.
Tony Ruth,

Risposte:


4

Gelatina , 13 10 byte

I.ịṚjI+2\H

Provalo online!

Come funziona

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 byte

2/d1)6Mh8Mt0)h+

TryItOnline

Metà del vettore di ingresso, e prende successive differenze, che invia d=[i(2)-i(1) i(3)-i(2) ... i(end)-i(end-1)]/2e quindi fa due vettori modificati, [d(1) d]e [d d(end)], e li aggiunge.

La versione precedente era migliore (perché convoluzione), ma 21 byte

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

1
Vedo, abbastanza intelligente. Quindi prendi un elenco di differenze in avanti e un elenco di differenze all'indietro e fai una media per ottenere la differenza centrale. Quindi gli endpoint vengono corretti calcolando invece la media di 2 differenze in avanti o 2 differenze all'indietro (nello stesso punto). Dal momento che la differenza in avanti e all'indietro sono appena spostate l'una dall'altra di un punto, puoi riutilizzare molta struttura.
Tony Ruth,

Inoltra solo le differenze, altrimenti sì. Fare (y(i)-y(i-1))+(y(i+1)-y(i))y(i+1)-y(i-1), che è il doppio della differenza centrata.
David,

3

Python con NumPy, 29 byte

import numpy;numpy.gradient

Questo sembra essere il comportamento predefinito della gradientfunzione di NumPy . I byte sono stati contati secondo questo consenso .


1

05AB1E, 20 19 17 14 byte

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

spiegato

¥Ð              # 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]

Provalo online

Salvato 2 byte grazie a @Adnan



1

Pyth, 14 byte

.OM>L2._seB-Vt

Provalo online: dimostrazione

Spiegazione:

.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 byte

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

Simile all'approccio utilizzato nella soluzione di @ 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

Spiegazione

[:((,{:)+{.,])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 byte

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 byte

.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

Provalo online!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.