Derivada na borda

9

Minha maneira preferida de aproximar uma derivada é a diferença central, é mais precisa do que a diferença direta ou a reversa, e estou com preguiça de ir em uma ordem superior. Mas a diferença central requer um ponto de dados em cada lado do ponto que você está avaliando. Normalmente, isso significa que você acaba não tendo uma derivada em nenhum dos pontos de extremidade. Para resolvê-lo, quero que você mude para a diferença para frente e para trás nas bordas:

Especificamente, quero que você use uma diferença para a frente no primeiro ponto, uma diferença para trás no último ponto e uma diferença central para todos os pontos no meio. Além disso, você pode assumir que os valores x estão espaçados igualmente e se concentrar apenas em y. Use estas fórmulas:

insira a descrição da imagem aqui

Boa sorte, estou ansioso para ver se alguém cria uma regra simples que reproduza todos os três derivados nos lugares certos!

ENTRADA EX:

0.034  9.62    8.885   3.477   2.38

Usarei FD, CD e BD para indicar qual algoritmo usar em qual ponto, portanto, acima de 5 pontos são usados ​​para aproximar derivadas usando

FD     CD      CD      CD     BD

E os valores calculados seriam:

9.586  4.4255 -3.0715 -3.2525 -1.097 

Você pode assumir que sempre haverá pelo menos 3 pontos de entrada e pode calcular usando precisão simples ou dupla.

E, como sempre, a resposta mais curta vence.

Tony Ruth
fonte
3
Apenas um nitpick, diferenças central / frente / trás são apenas aproximações de derivadas em um ponto, não as próprias derivadas.
Liam
Eu não entendo o que cada número de entrada e saída corresponde.
xnor
@ xnor, eu coloquei uma breve descrição entre a entrada e a saída explicando qual algoritmo usar para qual ponto de dados. Faz sentido agora?
Tony Ruth
Sim, acho que faz sentido. Para 5 entradas, você faria [a,b,c,d,e] -> [b-a,(c-a)/2,(d-b)/2,(e-c)/2,e-d]. Pode haver menos que 3 pontos de entrada?
Xnor
@xnor, está certo. E atualizei para que você possa assumir pelo menos três pontos de entrada.
Tony Ruth

Respostas:

4

Gelatina , 13 10 bytes

I.ịṚjI+2\H

Experimente online!

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

MATL, 21 15 bytes

2/d1)6Mh8Mt0)h+

TryItOnline

Metade o vetor de entrada e pega diferenças sucessivas para fornecer d=[i(2)-i(1) i(3)-i(2) ... i(end)-i(end-1)]/2e, em seguida , cria dois vetores modificados, [d(1) d]e [d d(end)], e os adiciona.

A versão anterior era melhor (por convolução), mas 21 bytes

d1j)6M1)6MTT2/H3$Y+bv
David
fonte
11
Entendo, muito esperto. Então você pega uma lista de diferenças avançadas e uma lista de diferenças anteriores e calcula a média delas para obter a diferença central. Em seguida, os pontos de extremidade são fixados, calculando a média de 2 diferenças para frente ou 2 para trás (no mesmo local). Como as diferenças de avanço e retrocesso são trocadas apenas um ponto, é possível reutilizar muita estrutura.
Tony Ruth
Encaminhe diferenças, caso contrário, sim. Fazer (y(i)-y(i-1))+(y(i+1)-y(i))y(i+1)-y(i-1), que é o dobro da diferença centralizada.
David David
3

Python com NumPy, 29 bytes

import numpy;numpy.gradient

Esse é o comportamento padrão da gradientfunção NumPy . Os bytes foram contados de acordo com esse consenso .

Martin Ender
fonte
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]

Experimente online

Guardado 2 bytes graças a @Adnan

Emigna
fonte
1

Pitão, 14 bytes

.OM>L2._seB-Vt

Experimente online: Demonstração

Explicação:

.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
fonte
1

J, 21 bytes

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

Semelhante à abordagem usada na solução 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

Explicação

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

Pitão - 29 bytes

Abordagem simples estúpida.

s[_-F<Q2mc-@Qhd@Qtd2tUtQ_-F>2

Experimente online aqui .

Maltysen
fonte
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])
Neil
fonte
0

Pitão, 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

Experimente online!

Freira Furada
fonte