Derivat am Rande

9

Mein bevorzugter Weg, eine Ableitung zu approximieren, ist der zentrale Unterschied, der genauer ist als der Vorwärts- oder Rückwärtsunterschied, und ich bin zu faul, um eine höhere Ordnung zu erreichen. Der zentrale Unterschied erfordert jedoch einen Datenpunkt auf beiden Seiten des Punktes, den Sie auswerten. Normalerweise bedeutet dies, dass Sie an keinem der Endpunkte eine Ableitung haben. Um es zu lösen, möchte ich, dass Sie an den Rändern auf Vorwärts- und Rückwärtsdifferenz umschalten:

Insbesondere möchte ich, dass Sie eine Vorwärtsdifferenz für den ersten Punkt, eine Rückwärtsdifferenz für den letzten Punkt und eine zentrale Differenz für alle Punkte in der Mitte verwenden. Sie können auch davon ausgehen, dass die x-Werte gleichmäßig verteilt sind und sich nur auf y konzentrieren. Verwenden Sie diese Formeln:

Geben Sie hier die Bildbeschreibung ein

Viel Glück, ich freue mich darauf zu sehen, ob jemand eine einfache Regel findet, die alle 3 Derivate an den richtigen Stellen reproduziert!

EX INPUT:

0.034  9.62    8.885   3.477   2.38

Ich werde FD, CD und BD verwenden, um anzugeben, welcher Algorithmus an welcher Stelle verwendet werden soll. Daher werden über 5 Punkte verwendet, um Ableitungen mit zu approximieren

FD     CD      CD      CD     BD

Und dann wären die berechneten Werte:

9.586  4.4255 -3.0715 -3.2525 -1.097 

Sie können davon ausgehen, dass immer mindestens 3 Eingabepunkte vorhanden sind, und Sie können mit einfacher oder doppelter Genauigkeit berechnen.

Und wie immer gewinnt die kürzeste Antwort.

Tony Ruth
quelle
3
Nur ein Trottel, zentrale / Vorwärts- / Rückwärtsdifferenzen sind nur Annäherungen an Derivate an einem Punkt, nicht die Derivate selbst.
Liam
Ich verstehe nicht, was jede Eingangs- und Ausgangsnummer entspricht.
xnor
@xnor, ich habe eine kurze Beschreibung zwischen Eingabe und Ausgabe eingefügt, in der erklärt wird, welcher Algorithmus für welchen Datenpunkt verwendet werden soll. Macht es jetzt Sinn?
Tony Ruth
Ja, ich denke es macht Sinn. Für 5 Eingänge würden Sie tun [a,b,c,d,e] -> [b-a,(c-a)/2,(d-b)/2,(e-c)/2,e-d]. Kann es weniger als 3 Eingabepunkte geben?
xnor
@xnor, das stimmt. Und ich habe aktualisiert, sodass Sie mindestens 3 Eingabepunkte annehmen können.
Tony Ruth

Antworten:

4

Gelee , 13 10 Bytes

I.ịṚjI+2\H

Probieren Sie es online aus!

Wie es funktioniert

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]. 
Dennis
quelle
3

MATL, 21 15 Bytes

2/d1)6Mh8Mt0)h+

TryItOnline

Hälften der Eingangsvektor, und nimmt aufeinanderfolgende Unterschiede zu geben , d=[i(2)-i(1) i(3)-i(2) ... i(end)-i(end-1)]/2und dann macht zwei modifizierte Vektoren, [d(1) d]und [d d(end)], und addiert sie.

Die ältere Version war besser (wegen Faltung), aber 21 Bytes

d1j)6M1)6MTT2/H3$Y+bv
David
quelle
1
Ich verstehe, ziemlich schlau. Sie nehmen also eine Liste der Vorwärtsunterschiede und eine Liste der Rückwärtsunterschiede und mitteln sie, um den zentralen Unterschied zu erhalten. Dann werden die Endpunkte festgelegt, indem stattdessen 2 Vorwärtsdifferenzen oder 2 Rückwärtsdifferenzen (an derselben Stelle) gemittelt werden. Da die Vorwärts- und Rückwärtsdifferenz nur um einen Punkt voneinander verschoben sind, können Sie viel Struktur wiederverwenden.
Tony Ruth
Nur Unterschiede weiterleiten, sonst ja. Tun (y(i)-y(i-1))+(y(i+1)-y(i))gibt y(i+1)-y(i-1), was doppelt so groß ist wie der zentrierte Unterschied.
David
3

Python mit NumPy, 29 Bytes

import numpy;numpy.gradient

Dies ist das Standardverhalten der NumPy- gradientFunktion. Die Bytes wurden gemäß diesem Konsens gezählt .

Martin Ender
quelle
1

05AB1E, 20 19 17 14 Bytes

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

Erklärt

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

Probieren Sie es online aus

2 Bytes dank @Adnan gespeichert

Emigna
quelle
1

Pyth, 14 Bytes

.OM>L2._seB-Vt

Probieren Sie es online aus: Demonstration

Erläuterung:

.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 ^
Jakube
quelle
1

J, 21 Bytes

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

Ähnlich wie bei der Lösung von @ David .

Verwendungszweck

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

Erläuterung

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

Probieren Sie es online aus!

Undichte Nonne
quelle