Encontrar aproximações polinomiais de uma onda senoidal


16

Eu quero aproximar a onda senoidal dada por aplicando um formador de ondas polinomial a uma onda triangular simples , gerada pela funçãosin(πx)

T(x)=14|12mod(12x+14, 1)|

onde é a parte fracionária de :mod(x,1)x

mod(x,y)y(xyxy)

Uma série de Taylor poderia ser usada como um formador de ondas.

S1(x)=πx2πx233!+πx255!πx277!

Dadas as funções acima, S1(T(x)) nos proporcionará uma aproximação decente de uma onda senoidal. Mas precisamos subir até a 7ª potência da série para obter um resultado razoável, e os picos são um pouco baixos e não terão uma inclinação exatamente igual a zero.

Em vez da série Taylor, poderíamos usar um modelador de ondas polinomial seguindo algumas regras.

  • Deve passar por -1, -1 e + 1, + 1.
  • A inclinação em -1, -1 e + 1, + 1 deve ser zero.
  • Deve ser simétrico.

Uma função simples que atende aos nossos requisitos:

S2(x)=3x2x32

Os gráficos de S2(T(x)) e sin(πx) estão bem próximos, mas não tão próximos quanto a série de Taylor. Entre os picos e os cruzamentos de zero, eles visivelmente se desviam um pouco. Uma função mais pesada e precisa, atendendo aos nossos requisitos:

S3(x)=x(x25)216

Provavelmente, isso é próximo o suficiente para meus propósitos, mas fico imaginando se existe outra função que se aproxima mais da onda senoidal e é computacionalmente mais barata. Eu tenho uma noção muito boa de como encontrar funções que atendam aos três requisitos acima, mas não tenho certeza de como encontrar funções que atendam a esses requisitos e também se assemelhem mais a uma onda senoidal.

Quais métodos existem para encontrar polinômios que imitam uma onda senoidal (quando aplicados a uma onda triangular)?


Para esclarecer, não estou necessariamente procurando apenas polinômios ímpares-simétricos, embora essas sejam a escolha mais direta.

Algo como a seguinte função também pode atender às minhas necessidades:

S4(x)=3x2+x24+x44

Isso atende aos requisitos na faixa negativa e uma solução por partes pode ser usada para aplicá-la também na faixa positiva; por exemplo

3x2P(x,2)4P(x,4)4

onde é a função de potência assinada .P

Eu também estaria interessado em soluções usando a função power assinada para suportar expoentes fracionários, pois isso nos dá outro "botão para girar" sem adicionar outro coeficiente.

a0x +a1P(x, p1)

Dadas as constantes corretas, isso poderia potencialmente obter uma precisão muito boa sem o peso dos polinômios de quinta ou sétima ordem. Aqui está um exemplo que atende aos requisitos descritos aqui usando algumas constantes escolhidas a dedo: .a0=1.666¯,a1=0.666¯,p1=2.5

5x2P(x, 52)3

Na verdade, essas constantes são muito perto de , e , e . Conectá-los fornece algo que parece extremamente próximo a uma onda senoidal. 1-ππ2 e1π2e

π2x +(1π2)P(x,e)

Em outras , parece muito próximo de entre 0,0 e π / 2,1. Alguma opinião sobre o significado disso? Talvez uma ferramenta como o Octave possa ajudar a descobrir as "melhores" constantes para essa abordagem. sin(x)xxe6sin(x)


1
então, qual é a sua definição de termo de erro para "mais próximo"? Tanto quanto eu poderia dizer, a série de Taylor que você citou é o erro mínimo de L² aproximado para um número finito de coeficientes. (Eu penso.)
Marcus Müller

2
A propósito, qual é o seu objetivo? Pode realmente ajudar a nos dizer por que você está procurando um modelador de ondas polinomial, em que base tecnológica e quais são seus principais objetivos para a aproximação.
Marcus Müller

@ MarcusMüller Estou disposto a sacrificar a precisão da série Taylor por algo significativamente mais barato, se for indistinguível de uma onda senoidal para o ouvido humano. Os picos da aproximação da série Taylor também me incomodam. Estou interessado em encontrar algo "mais próximo" do que as outras duas funções que listei. Eu suspeito que não vai ficar mais barato do que . S2
Convidado

1
"Para o ouvido humano" é fundamental aqui :) Por que os picos "incomodam" você? Novamente: nos dê uma idéia do porquê / com que finalidade e sob quais restrições você está fazendo isso. Sem antecedentes suficientes, sua pergunta é simplesmente ampla demais para ser respondida corretamente!
Marcus Müller

1
Por que você está começando com uma onda triangular? Sine-geradores são simples e comum, ondas quadradas são trivialmente filtrada para a harmônica fundamentais, etc.
Carl Witthoft

Respostas:


10

cerca de uma década atrás eu fiz isso para uma empresa de sintetizadores de música sem nome que tinha P&D não muito longe do meu condomínio em Waltham MA. (Não consigo imaginar quem são.) Não tenho os coeficientes.

mas tente o seguinte:

f(x)sin(π2x)for 1x+1=π2x(a0+a1x2+a2x4)

isso garante que .f(x)=f(x)

Para garantir que entãof(x)|x=±1=0

f(x)=π2(a0+3a1x2+5a2x4)

(1)a0+3a1+5a2=0

Essa é a primeira restrição. Para garantir que , então|f(±1)|=1

(2)a0+a1+a2=2π

Essa é a segunda restrição. Eliminando e resolvendo as Eqs. (1) e (2) para em termos de (que resta ajustar):a 2 a 1a0a2a1

a0=52π12a1

a2=12π12a1

Agora você tem apenas um coeficiente, , que pode ser modificado para obter o melhor desempenho:a1

f(x)=π2x((52π12a1)+a1x2(12π+12a1)x4)

É dessa maneira que eu ajustaria o para obter o melhor desempenho para um oscilador de onda senoidal. Eu ajustaria o uso acima e a simetria da onda senoidal em torno de e colocaria exatamente um ciclo inteiro em um buffer com uma potência de dois números de pontos (digamos 128, não me importo) e executaria a FFT nesse ciclo perfeito. x = 1a1x=1

O compartimento de resultado 1 da FFT será a força do seno e deve ser de cerca de . Agora você pode ajustar para aumentar e diminuir a distorção da 3ª harmônica. Eu começaria com para que . Isso está no compartimento 3 dos resultados da FFT. Mas a distorção do 5º harmônico (valor no compartimento 5) será conseqüente (aumentará à medida que o terceiro harmônico diminuir). Eu ajustaria para que a força do 5º nível harmônico seja igual ao 3º nível harmônico. Será em torno de -70 dB a partir do 1º harmônico (se bem me lembro). Essa será a onda senoidal mais agradável de um polinômio barato, de 3-coeficiente, 5ª ordem e ímpar-simétrico.a 1 a 15N/2a1a01a1a15π2a01a1

Outra pessoa pode escrever o código MATLAB. Como isso soa para você?


Definitivamente, não terei tempo para fazer o MATLABing para procurar o ideal, de modo que o terceiro harmônico seja igual ao quinto harmônico, cerca de 70 dB abaixo do fundamental (1º harmônico). alguém precisa fazer isso. Desculpe. a1
22818 Robert Bristow-

Ótima resposta, ainda digerindo. Na verdade, começa a se perguntar se ele precisa ser um polinômio de 3-coeficiente, 5ª ordem e ímpar-simétrico ... O seu f '(x) realmente pode ser f (x) e ser um acordo por partes igual a 0? Esboço aproximado aqui . Talvez seja isso que Ced tenha em mente? Ainda alcançando vocês.
Convidado

Esta é uma abordagem bonita. Gostaria de saber se, em vez de pegar a FFT e resolver iterativamente, você poderia formar os polinômios de Chebyshev de terceira e quinta ordem a partir do seu , então igualar os dois e resolver a ? f(x)a1
Speedy

Deve ter sido meio adormecido quando eu postei que "esboço", eu quis fazer algo como isso , mas corrigido para ser executado através ± 1 e têm inclinação zero (pode apenas tomar o, em torno de violino derivado com ele, integrá-lo novamente). Não tenho certeza se há alguma vantagem sobre a quinta ordem, algo que eu ainda não havia considerado.
Guest

1
Esta é realmente uma solução brilhante, demorou um pouco para entrar. Espero que marcá-la como correta não impeça que alguém apareça e escreva o código.
Convidado

9

O que geralmente é feito é uma aproximação que minimiza algumas normas do erro, geralmente a forma (onde o erro máximo é minimizado) ou a forma L 2 (onde o erro quadrado médio é minimizado). L -approximation é feito usando o algoritmo de troca de Remez . Tenho certeza que você pode encontrar algum código-fonte aberto implementando esse algoritmo. No entanto, neste caso, acho que uma otimização l 2 muito simples (discreta) é suficiente. Vejamos alguns códigos do Matlab / Octave e os resultados:LL2Ll2

x = espaço interno (0, pi / 2.300); % grade em [0, pi / 2]
x = x (:);
% sistema sobredeterminado de equações lineares
% (usando apenas poderes ímpares)
A3 = [x, x. ^ 3];
A5 = [x, x. ^ 3, x. ^ 5];
b = sin (x);
% de resolução no sentido l2
c3 = A3 \ b;
c5 = A5 \ b;
f3 = A3 * c3; % Aproximação de terceira ordem
f5 = A5 * c5; % Aproximação de 5ª ordem

A figura abaixo mostra os erros de aproximação para o -order e para o 5 t h -order aproximações. Os erros máximos de aproximação são e , respectivamente.3rd5th8.8869e-031.5519e-04

insira a descrição da imagem aqui

Os coeficientes ótimos são

c3 =
   0.988720369237930
  -0.144993929056091

e

c5 =
   0.99976918199047515
  -0.16582163562776930
   0.00757183954143367

Portanto, a aproximação de terceira ordem é

(1)sin(x)0.988720369237930x0.144993929056091x3,x[π/2,π/2]

e a aproximação de quinta ordem é

(2)sin(x)0.99976918199047515x0.16582163562776930x3+0.00757183954143367x5,x[π/2,π/2]

EDITAR:

Dei uma olhada nas aproximações com a função de potência assinada, conforme sugerido na pergunta, mas a melhor aproximação dificilmente é melhor do que a aproximação de terceira ordem mostrada acima. A função de aproximação é

(3)f(x)=x1p(π2)1pxp,x[0,π/2]

onde as constantes foram escolhidos de tal modo que e f ' ( π / 2 ) = 0 . A potência p foi otimizada para obter o menor erro máximo no intervalo [ 0 , π / 2 ] . O valor ótimo para p foi encontrado como p = 2,774 . A figura abaixo mostra os erros de aproximação para a aproximação de terceira ordem ( 1 ) e para a nova aproximação ( 3f(0)=1f(π/2)=0p[0,π/2]pp=2.774(1) :(3)

insira a descrição da imagem aqui

O erro máximo de aproximação da aproximação é , mas observe que a aproximação de terceira ordem só excede esse erro próximo de π / 2 e que, na maioria das vezes, seu erro de aproximação é realmente menor que o da função de potência assinada.(3)4.5e-3π/2

EDIT 2:

Se você não se importa com a divisão, também pode usar a fórmula de aproximação senoidal de Bhaskara I , que possui um erro máximo de aproximação de 1.6e-3:

(4)sin(x)16x(πx)5π24x(πx),x[0,π/2]

Isso é muito útil, obrigado. Esta é a primeira vez que usei o Octave. Eu segui a maioria, mas como você obteve os gráficos de erro de aproximação e os valores máximos?
Convidado

1
@ Guest: Os erros são justos b-f3e b-f5, respectivamente. Use o plotcomando para plotá-los.
Matt L.

1
@ Guest: E os máximos que você recebe max(abs(b-f3))e max(abs(b-f5)).
Matt L.

@ Guest: Eu brinquei com a função de poder assinado, mas o resultado não é significativamente melhor do que a aproximação de terceira ordem que eu tinha antes. Confira minha resposta editada. Quanto à complexidade, isso faria uma diferença tão grande?
Matt L.

Obrigado por investigar. A complexidade não é grande coisa, apenas é curioso o quão precisa pode ser a aproximação com uma complexidade relativamente baixa. Não tenho muita certeza de como você criou (3), mas funciona muito bem. Eu precisaria usar 2.752 em vez disso p, pois qualquer coisa acima disso enviará os picos acima de 1 (recorte).
Convidado

7

Comece com um polinômio parametrizado de 5ª ordem de simetria ímpar geral :

f(x)=a0x1+a1x3+a2x5=x(a0+a1x2+a2x4)=x(a0+x2(a1+a2x2))

Agora, colocamos algumas restrições nessa função. A amplitude deve ser 1 nos picos, ou seja, f(1)=1 . Substituindo 1 por x obtém-se:

(1)a0+a1+a2=1

Essa é uma restrição. A inclinação nos picos deve ser zero, ou seja, f(1)=0 . A derivada de f(x) é

a0+3a1x2+5a2x4

e substituir 1 por x fornece nossa segunda restrição:

(2)a0+3a1+5a2=0

Agora podemos usar nossas duas restrições para resolver para a1 e a2 em termos de a0 .

(3)a1=522a0a2=a032

Tudo o que resta é ajustar a0 para obter um bom ajuste. Aliás, a0 (e a inclinação na origem) acaba sendo π2 , como podemos ver a partir de umgráficoda função.

Otimização de parâmetros

Abaixo estão algumas otimizações dos coeficientes, que resultam nessas amplitudes relativas dos harmônicos em comparação com a frequência fundamental (1º harmônico):

Comparação de aproximações

Na complexa série de Fourier :

k=ckei2πPkx,

de um verdadeiro P- forma de onda periódica com P=4 e tempo de simetria sobre x=1 e com metade de um período definido pelo ângulo diferente função f(x) sobre 1x1, o coeficiente de a kth exponencial complexa harmónica é:

ck=1P11+P({f(x)if x<1f(x2)if x1)ei2πPkxdx.

Devido à relação 2cos(x)=eix+eix (veja a fórmula de Euler ), a amplitude de um harmônico sinusoidal real com k>0 é 2|ck|, que é o dobro da magnitude do exponencial complexo da mesma frequência. Isso pode ser massageado de uma forma que facilita para alguns softwares de matemática simbólica simplificar a integral:

2|ck|=24|13({f(x)if x<1f(x2)if x1)ei2π4kxdx|=12|11f(x)eiπ2kxdx13f(x2)eiπ2kxdx|=12|11f(x)eiπ2kxdx11f(x+22)eiπ2k(x+2)dx|=12|11f(x)eiπ2kxdx11f(x)eiπ2k(x+2)dx|=12|11f(x)(eiπ2kxeiπ2k(x+2))dx|=12|eiπ2x11f(x)(eiπ2kxeiπ2k(x+2))dx|=12|11f(x)(eiπ2k(x1)eiπ2k(x+1))dx|

O exposto acima tira proveito disso |eix|=1 para x. real . É mais fácil para alguns sistemas de álgebra computacional simplificar a integral assumindo que k é real e simplificar para o número k no final. O Wolfram Alpha pode integrar termos individuais da integral final correspondente aos termos do polinômio f(x) . Para os coeficientes dados na Eq. 3 temos amplitude:

=|48((1)k1)(16a0(π2k210)5×(5π2k248))π6k6|

5ª ordem, derivada contínua

Nós podemos resolver para o valor de a0 que dá igual amplitude 2|ck|do 3º e 5º harmônico. Haverá duas soluções correspondentes ao 3º e 5º harmônicos com fases iguais ou opostas. A melhor solução é a que minimiza a amplitude máxima dos 3º e acima dos harmônicos e, equivalentemente, a amplitude relativa máxima dos 3º e acima dos harmônicos em comparação com a frequência fundamental (1º harmônico):

a0=3×(132375π2130832)16×(15885π216354)1.569778813,a1=522a0=79425π2654168×(15885π2+16354)0.6395576276,a2=a032=15885π216×(15885π216354)0.06977881382.

Isso fornece a frequência fundamental na amplitude 1367961615885π616354π41.000071420e o 3º e o 5º harmônicos em amplitude relativa18906 ou cerca de78.99 dBcomparação com a frequência fundamental. Umkthharmônico tem amplitude relativa(1(1)k)|8177k279425|142496k6.

7ª ordem, derivada contínua

Da mesma forma, a aproximação polinomial ideal de 7ª ordem com as mesmas restrições iniciais e o 3º, 5º e 7º harmônico no menor nível igual possível é:

f(x)=a0x1+a1x3+a2x5+a3x7=x(a0+a1x2+a2x4+a3x7)=x(a0+x2(a1+x2(a2+a3x2)))

a0=2a2+4a3+321.570781972,a1=4a2+6a3+120.6458482979,a2=347960025π4405395408π216×(281681925π4405395408π2+108019280)0.07935067784,a3=16569525π416×(281681925π4405395408π2+108019280)0.004284352588.

2293523251200281681925π8405395408π6+108019280π40.9999983752,11555395123.8368 dBcomparação com o fundamental. Umkthharmônico tem amplitude relativa(1(1)k)|1350241k450674426k2+347960025|597271680k8 comparação com o fundamental.

5ª ordem

Se o requisito de uma derivada contínua for descartado, a aproximação de 5ª ordem será mais difícil de resolver simbolicamente, porque a amplitude do 9º harmônico aumentará acima da amplitude do 3º, 5º e 7º harmônico, se esses forem restritos a serem igual e minimizado. Testando 16 soluções diferentes correspondentes a diferentes subconjuntos de três harmônicos de {3,5,7,9} com amplitude igual e fases iguais ou opostas, a melhor solução é:

f(x)=a0x1+a1x3+a2x5a0=1a1a21.570034357a1=3×(2436304π22172825π4)8×(1303695π41827228π2+537160)0.6425216143a2=1303695π416×(1303695π41827228π2+537160)0.07248725712

10804305921303695π61827228π4+537160π20.9997773320.726377791.52 dB,7260833103310027392.6 dBkth(1(1)k)|67145k42740842k2+19555425|33763456k6.

x=±1x±1.002039940.x=10.004905799828k,

7ª ordem

Uma aproximação de 7ª ordem sem derivada contínua pode ser encontrada da mesma forma. A abordagem requer o teste de 120 soluções diferentes e foi automatizada pelo script Python no final desta resposta. A melhor solução é:

f(x)=a0x1+a1x3+a2x5+a3x7a0=1a1a2a31.5707953785726114835a1=5×(4374085272375π66856418226992π4+2139059216768π2)16×(2124555703725π63428209113496π4+1336912010480π2155807094720)0.64590724797262922190a2=2624451163425π63428209113496π416×(2124555703725π63428209113496π4+1336912010480π2155807094720)0.079473610232926783079a3=124973864925π616×(2124555703725π63428209113496π4+1336912010480π2155807094720)0.0043617408329090447344

169918012823961602124555703725π83428209113496π6+1336912010480π4155807094720π21.0000024810802368487.502400688077133.627 dB.kth(1(1)k)|162299057k6+16711400131k4428526139187k2+2624451163425|4424948250624k8.

Fonte Python

from sympy import symbols, pi, solve, factor, binomial

numEq = 3 # Number of equations
numHarmonics = 6 # Number of harmonics to evaluate

a1, a2, a3, k = symbols("a1, a2, a3, k")
coefficients = [a1, a2, a3]
harmonicRelativeAmplitude = (2*pi**4*a1*k**4*(pi**2*k**2-12)+4*pi**2*a2*k**2*(pi**4*k**4-60*pi**2*k**2+480)+6*a3*(pi**6*k**6-140*pi**4*k**4+6720*pi**2*k**2-53760)+pi**6*k**6)*(1-(-1)**k)/(2*k**8*(2*pi**4*a1*(pi**2-12)+4*pi**2*a2*(pi**4-60*pi**2+480)+6*a3*(pi**6-140*pi**4+6720*pi**2-53760)+pi**6))

harmonicRelativeAmplitudes = []
for i in range(0, numHarmonics) :
    harmonicRelativeAmplitudes.append(harmonicRelativeAmplitude.subs(k, 3 + 2*i))

numCandidateEqs = 2**numHarmonics
numSignCombinations = 2**numEq
useHarmonics = range(numEq + 1)

bestSolution = []
bestRelativeAmplitude = 1
bestUnevaluatedRelativeAmplitude = 1
numSolutions = binomial(numHarmonics, numEq + 1)*2**numEq
solutionIndex = 0

for i in range(0, numCandidateEqs) :
    temp = i
    candidateNumHarmonics = 0
    j = 0
    while (temp) :
        if (temp & 1) :
            if candidateNumHarmonics < numEq + 1 :
                useHarmonics[candidateNumHarmonics] = j
            candidateNumHarmonics += 1
        temp >>= 1
        j += 1
    if (candidateNumHarmonics == numEq + 1) :
        for j in range(0,  numSignCombinations) :
            eqs = []
            temp = j
            for n in range(0, numEq) :
                if temp & 1 :
                    eqs.append(harmonicRelativeAmplitudes[useHarmonics[0]] - harmonicRelativeAmplitudes[useHarmonics[1+n]])
                else :
                    eqs.append(harmonicRelativeAmplitudes[useHarmonics[0]] + harmonicRelativeAmplitudes[useHarmonics[1+n]])
                temp >>= 1
            solution = solve(eqs, coefficients, manual=True)
            solutionIndex += 1
            print "Candidate solution %d of %d" % (solutionIndex, numSolutions)
            print solution
            solutionRelativeAmplitude = harmonicRelativeAmplitude
            for n in range(0, numEq) :                
                solutionRelativeAmplitude = solutionRelativeAmplitude.subs(coefficients[n], solution[0][n])
            solutionRelativeAmplitude = factor(solutionRelativeAmplitude)
            print solutionRelativeAmplitude
            solutionWorstRelativeAmplitude = 0
            for n in range(0, numHarmonics) :
                solutionEvaluatedRelativeAmplitude = abs(factor(solutionRelativeAmplitude.subs(k, 3 + 2*n)))
                if (solutionEvaluatedRelativeAmplitude > solutionWorstRelativeAmplitude) :
                    solutionWorstRelativeAmplitude = solutionEvaluatedRelativeAmplitude
            print solutionWorstRelativeAmplitude
            if (solutionWorstRelativeAmplitude < bestRelativeAmplitude) :
                bestRelativeAmplitude = solutionWorstRelativeAmplitude
                bestUnevaluatedRelativeAmplitude = solutionRelativeAmplitude                
                bestSolution = solution
                print "That is a new best solution!"
            print

print "Best Solution is:"
print bestSolution
print bestUnevaluatedRelativeAmplitude
print bestRelativeAmplitude

Essa é uma variação da resposta de Robert, e é o caminho que eu finalmente tomei. Vou deixar aqui para o caso de ajudar mais alguém.
Convidado

uau, resolvendo analiticamente. eu usaria apenas o MATLAB e um FFT e meio que procuramos a resposta.
você fez muito bem.
22418 Robert De Bristow-johnson

2
Na verdade, @OlliNiemitalo, acho que -79 dB é bom o suficiente para a implementação de um oscilador de onda senoidal de sintetizador digital. ele pode ser acionado por uma onda triangular, que é gerada facilmente a partir do valor abs de um dente de serra, que é mais facilmente gerada com um acumulador de fase de ponto fixo.
ninguém ouvirá a diferença entre essa onda senoidal polinomial de 5ª ordem e um seno puro.
Robert Bristow-johnson

1
fff

1
f0

5

Você está perguntando isso por razões teóricas ou uma aplicação prática?

Geralmente, quando você tem uma função cara de calcular em um intervalo finito, a melhor resposta é um conjunto de tabelas de pesquisa.

Uma abordagem é usar as parábolas mais adequadas:

n = piso (x * N + 0,5);

d = x * N - n;

i = n + N / 2;

y = L_0 + L_1 [i] * d + L_2 [i] * d * d;

Ao encontrar a parábola em cada ponto que atenda aos valores de d sendo -1/2, 0 e 1/2, em vez de usar as derivadas em 0, você garante uma aproximação contínua. Você também pode alterar o valor x, em vez do índice da matriz, para lidar com seus valores x negativos.

Ced

===================================================

Acompanhamento:

A quantidade de esforço e os resultados que foram encontrados para encontrar boas aproximações é muito impressionante. Eu estava curioso para saber como minha solução parabólica chata e sem graça seria comparada. Não surpreendentemente, faz muito melhor. Aqui estão os resultados:

   Método Mínimo Máximo Médio RMS
  -------- -------- -------- -------- --------
     Potência -8.48842 1.99861 -4.19436 5.27002
    OP S_3 -2.14675 0.00000 -1.20299 1.40854
     Bhask -1,34370 1,63176 -0,14367 0,97353
     Relação -0,24337 0,22770 -0,00085 0,16244
     rbj 5 -0,06724 0,15519 -0,00672 0,04195
    Olli5C -0,16367 0,20212 0,01003 0,12668
     Olli5 -0,26698 0,00000 -0,15177 0,16402
    Olli7C -0,00213 0,00000 -0,00129 0,00143
     Olli7 -0,00005 0,00328 0,00149 0,00181
    Para16 -0,00921 0,00916 -0,00017 0,00467
    Para32 -0,00104 0,00104 -0,00001 0,00053
    Para64 -0,00012 0,00012 -0,00000 0,00006

Os valores representam 1000x o erro entre a aproximação e o real avaliado a cada 0,0001 de uma escala de 0 a 1 (inclusive), portanto, 10001 pontos no total. A escala é convertida para avaliar as funções de 0 aπ/2, exceto as equações de Olli Niemitalo que usam a escala de 0 a 1. Os valores das colunas devem ser claros nos cabeçalhos. Os resultados não mudam com um espaçamento de 0,001.

A linha "Power" é a equação: x-xe6.

A linha rbj 5 é igual à solução c5 de Matt L.

16, 32 e 64 são o número de intervalos que têm ajustes parabólicos. É claro que existem descontinuidades insignificantes na primeira derivada em cada limite de intervalo. Os valores da função são contínuos. Aumentar o número de intervalos apenas aumenta os requisitos de memória (e o tempo de inicialização), não aumenta a quantidade de cálculo necessária para a aproximação, que é menor que qualquer outra equação. Eu escolhi potências de dois porque uma implementação de ponto fixo poderia salvar uma divisão usando um AND nesses casos. Além disso, não queria que a contagem fosse proporcional à amostra de teste.

Eu executei o programa python de Olli Niemitalo e obtive isso como parte da impressão: "Solução candidata 176 de 120" Eu pensei que isso era estranho, por isso estou mencionando.

Se alguém quiser que eu inclua alguma das outras equações, informe-me nos comentários.

Aqui está o código para as aproximações parabólicas por partes. Todo o programa de teste é muito longo para ser postado.

# =================================================== ============================
def FillParab (argArray, argPieceCount):

# y = anúncio ^ 2 + bd + c

# ym = a .25 - b .5 + c
# y = c
# yp = a .25 + b .5 + c

# c = y
# b = yp - ym
# a = (yp + ym - 2y) * 2

# ---- Calcular matrizes de pesquisa

        theStep = pi * .5 / float (argPieceCount - 1)
        theHalf = theStep * .5

        theL0 = zeros (argPieceCount)
        theL1 = zeros (argPieceCount)
        theL2 = zeros (argPieceCount)

        para k no intervalo (0, argPieceCount):
         x = flutuante (k) * theStep

         ym = pecado (x - metade)
         y = pecado (x)
         yp = sin (x + meio)

         theL0 [k] = y
         theL1 [k] = yp - ym
         theL2 [k] = (yp + ym - 2,0 * y) * 2

# ---- Preencher

        theN = len (argArray)

        theFactor = pi * .5 / float (theN - 1)

        para i no intervalo (0, theN):
         x = flutuante (i) * o fator

         kx = x / theStep
         k = int (kx + 0,5)
         d = kx - k

         argArray [i] = theL0 [k] + (theL1 [k] + theL2 [k] * d) * d

# =================================================== ============================

=======================================

Apêndice

Eu incluí hóspedes S3função da postagem original como "OP S_3" e a fórmula de dois parâmetros do Guest nos comentários como "Proporção". Ambos estão na escala de 0 a 1. Eu não acho que o Ratio one seja adequado para cálculo em tempo de execução ou para a construção de uma tabela de pesquisa. Afinal, é significativamente mais computação para a CPU do que apenas uma chamada simples sin (). É interessante matematicamente.


Bom trabalho! Corrigi esse bug ("176 de 120").
Olli Niemitalo 3/02

Boa atualização, isso faz mais sentido para mim agora. ox-xe6 provavelmente não precisa ser testado, eu apenas joguei lá fora, porque eu estava tentando descobrir o significado de eque parecia continuar aparecendo enquanto eu brincava com isso. Uma melhor expressão racional para testar pode ser algo como isto:f0 0(x)=|x|umaplaca(x) ; b=f0 0(1) ; f1(x)=f0 0(x)-bx ; c=1f1(1) ; f2(x)=f1(x)c ... agora uma deve ser definido para cerca de 223...
Visitante

...ou f0 0(x)pode ser praticamente qualquer outra função simétrica ímpar; sigmóides parecem funcionar bem, comoumax-1umax+1 (mas o valor certo para umaprecisa ser encontrado, é claro). Aqui está um gráfico ... como Olli menciona, isso provavelmente não é prático para computação on-the-fly, mas acho que poderia ser útil para a construção de uma tabela de pesquisa.
Visitante

Ou uma versão mais precisa de 2 parâmetros, uma0 0x-uma1xuma0 0x+uma1x parece muito bom comuma0 013 e uma1109
Guest
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.