• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

Nazgulled

O que é que me está a escapar nesta equação?

24 mensagens neste tópico

Vejam isto:

http://www45.wolframalpha.com/input/?i=exponential+fit+0.004%2C+0.0045%2C+0.005%2C+0.0058%2C+0.0069%2C+0.0080%2C+0.0105%2C+0.0145%2C+0.0250%2C+0.0750

É precisamente a equação que estava à procura. Segundo o gráfico representado com aqueles valores introduzidos manualmente por mim, é exactamente o que eu preciso. Cada valor daqueles é o Y que corresponde ao X de 1 a 10.

Contudo, se substituir o X pelos respectivos valores, não obtenho o valor correcto que era suposto receber:

X = 1

http://www45.wolframalpha.com/input/?i=0.0000182311+*+e^(0.829327+*+1)

X = 2

http://www45.wolframalpha.com/input/?i=0.0000182311+*+e^(0.829327+*+2)

X = 4

http://www45.wolframalpha.com/input/?i=0.0000182311+*+e^(0.829327+*+4)

X = 6

http://www45.wolframalpha.com/input/?i=0.0000182311+*+e^(0.829327+*+6)

X = 8

http://www45.wolframalpha.com/input/?i=0.0000182311+*+e^(0.829327+*+8)

X = 10

http://www45.wolframalpha.com/input/?i=0.0000182311+*+e^(0.829327+*+10)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Tinha escrito um post decente mas o firefox passou-se... meh

Tu estás a usar o método dos mínimos quadrados para ajustar uma expressão do tipo y=a*e^(b*x) aos teus dados. Provavelmente estás surpreendido por os valores iniciais darem coisas tão disparatadas (i.e. pequenas).

Como o próprio nome indica este método acha os parâmetros a e b tais que a soma dos quadrados dos erros (ou seja os quadrados das diferenças entre a*e^(b*x) e os teus y) seja mínima. Isso implica que se alguns dos teus y são pequenos em módulo face a outros, vais notar que existe uma tendência para que o erro relativo (erro/valor y) seja muito maior nesses porque o método apenas tem em conta erros absolutos.

Por outro lado, mesmo os valores grandes não estão lá grande coisa e isso está a parecer-te estranho provavelmente porque no gráfico parece tudo quase perfeitinho. Neste caso já não tem nada a ver com a fórmula, é apenas uma questão de ilusão óptica, chamemos-lhe "mal da exponencial". Como ele te ajusta uma exponencial, e para valores à direita dos teus a exponencial toma valores muito maiores, a escala que daí resulta no gráfico faz-te pensar que os erros são insignificantes quando tal não é o caso.

Se olhares para o valor de R² que já deves ter visto ao fazer uma regressão linear, reparas que também não é nada de extraordinário (podia ser mais próximo de 1).

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Já agora, se pretendes obter uma expressão que passe exactamente por esse pontos apenas tens que interpolar por um polinómio de ordem n-1 em que n é o número de pontos que tens.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Mas isso tira toda a lógica em fazer uma expressão do genero.

A ideia não é apenas ter a expressão, a ideia era ter uma equação onde eu substituísse o valor de X para obter os valores de Y que preciso. Para minimizar o código na minha aplicação. Ao fazer um polinómio desse género, não ganho nada com ele e mais vale fazer um switch(X) e manualmente devolver os valores que preciso...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não percebi. Qual é a diferença entre "ter apenas a expressão" ou "ter uma equação onde substituis o valor de X para obter os valores de Y"?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

A ideia é não ter que guardar os valores de Y correspondentes, para isso é que eu queria uma equação que os calculasse.

Que vantagem tenho em ter um polinómio onde especificamente tenho de definir os valores que quero para cada X entre 1 e 10 só para calcular aquele tipo de curva? Eu não quero calcular a curva, a curva não me serve para nada. Eu só quero os valores de Y correspondentes a X entre 1 e 10 e queria uma equação que os calculasse só para simplificar o código.

O polinómio não ia trazer vantagem nenhuma nesse aspecto.

Que vantagem tenho eu em fazer isto:

Y = ax^4 + bx^3 + cx^2 + dx + e

Em vez de isto:

switch(x) {
    case 1: Y = a; break;
    case 2: Y = b; break;
    case 3: Y = c; break;
    case 4: Y = d; break;
    case 5: Y = e; break;
}

Não vejo grande vantagem porque eu não quero a curva para nada, não me interessa calcular valores de Y para X != de 1..10, só me interessa mesmo estes 10 e se para definir uma curva que calcule estes valores exactos preciso de ter um polinómio com 9 graus, não tenho vantagem nenhuma em usa-lo. Mais vale fazer o switch...

P.S: Posso estar aqui a trocar alguns valores e tal, mas acho que agora percebes onde quero chegar...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Também não tens grandes vantagens em fazer cálculos com uma equação em vez de usar um switch, que é muito rápido.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Se fosse uma equação simples tinha, era equivalentemente rápido e poupava linhas de código :confused: Claro que se a equação for complicada, não deve ter vantagem nenhuma e até poderia ser eventualmente bastante lento.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Então tu não estavas a tentar ajustar um modelo que te permitisse calcular outros valores...

Nunca imaginei que fosse isso porque nesse caso usaria um array (acesso constante -> rápido, 1 linha de código).

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Se fosse uma equação simples tinha, era equivalentemente rápido e poupava linhas de código :confused: Claro que se a equação for complicada, não deve ter vantagem nenhuma e até poderia ser eventualmente bastante lento.

Um switch compila normalmente para uma jump/lookup table, indepentemente  do número de cases, é sempre só necessária uma instrução para saber qual é o código certo a executar. Fazer cálculos com floating-point é bastante mais lento.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Então tu não estavas a tentar ajustar um modelo que te permitisse calcular outros valores...

Desde o inicio que disse que era entre 1 e 10, nem mais, nem menos.

Nunca imaginei que fosse isso porque nesse caso usaria um array (acesso constante -> rápido, 1 linha de código).

É outra hipótese, mas acho que prefiro o switch. Mas não vale a pena estar a analisar isto ao nível da máquina, até porque isso não me interessa para nada para aquilo que estou a fazer.

Um switch compila normalmente para uma jump/lookup table, indepentemente  do número de cases, é sempre só necessária uma instrução para saber qual é o código certo a executar. Fazer cálculos com floating-point é bastante mais lento.

Eu estava a falar a nível do meu código fonte, e não o do compilador. Imagina lá se tivesses 10 mil valores, ficava melhor um switch() com 10 mil cases ou uma equação que os calculasse? Se a equação não tivesse um grande overhead no tempo de execução, preferia uma linha de código do que esses cases todos.

Mas mais uma vez, isto não tem nada a ver com o nível da máquina, mas a nível do MEU código. A equação era só para minimizar isso. Obviamente que não ia usar uma equação que me tornasse a aplicação lenta, era só no caso de isso não acontecer.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Se era para minimizar código o que fazia sentido era usar um array.

Desde o inicio que disse que era entre 1 e 10, nem mais, nem menos.

Mas mais uma vez, isto não tem nada a ver com o nível da máquina, mas a nível do MEU código. A equação era só para minimizar isso.

Sim entre 1 e 10 existem inúmeros valores. Geralmente quando alguém usa um modelo de ajuste é porque quer estimar valores que não conhece, como nunca disseste qual era o propósito, supus que estava relacionado com as aplicações habituais dos modelos de ajuste.

Se queres minimizar código o que faria sentido era usar um array e não um switch.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Se fosse para ter em conta os valores TODOS entre 1 e 10 não apenas inteiros, eu tinha mencionado isso :confused:

Uma das intenções era minimizar o código e como não era o único objectivo, vou ficar-me pelo switch. Mas não vale a pena debater isto. Até porque não tem nada a ver com o assunto do tópico...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Uma das intenções era minimizar o código e como não era o único objectivo, vou ficar-me pelo switch. Mas não vale a pena debater isto. Até porque não tem nada a ver com o assunto do tópico...

Ooooh... mas eu queria saber :confused:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O que é que as decisões que eu faço para a minha aplicação tem a ver com o que quer que seja? A não ser que eu coloque dúvidas sobre essas mesmas decisões, porquê que eu haveria de as querer debater?

A sério, não estou a perceber...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Nazgulled, já devias saber que os programadores hoje em dia são mais cuscuvilheiros do que os pedreiros :confused:;)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

E a solução clássica de por os valores de 1 a 10 num array? Não serve?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

E a solução clássica de por os valores de 1 a 10 num array? Não serve?

Ele já explicou... :)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Ele já explicou... :)

Ele disse que não o faria. Não explicou :)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não vale a pena continuarem a pedir explicações, a decisão é dele, ele quer usar uma fórmula fixa em vez de armazenar os valores.

@Nazgulled, precisas mesmo de uma função exponencial? Se não precisares, faz como o pedrosorio diz, interpolas um polinómio que dê esses valores. Não sei fazer isso, mas o WolframAlpha sabe: http://www45.wolframalpha.com/input/?i=interpolate+0.004,+0.0045,+0.005,+0.0058,+0.0069,+0.0080,+0.0105,+0.0145,+0.0250,+0.0750

Com essa função não tens erros nos valores que queres calcular. Pode é tornar o código lento, quando seria muito mais rápido usar um array, mas se é mesmo uma função que queres, podes sempre decompor isso para tornar os cálculos mais rápidos, pondo vários x em evidência para vários graus. Por exemplo, uma função cúbica como 2x^3 + 6x^2 + 4x + 1 pode ser reescrita como x ( x ( x ( 2 ) + 6 ) + 4 ) + 1.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Por exemplo, uma função cúbica como 2x^3 + 6x^2 + 4x + 1 pode ser reescrita como x ( x ( x ( 2 ) + 6 ) + 4 ) + 1.

Is that freaking lisp or what? :)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Is that freaking lisp or what? :)

Speeds it up :) Já ouvi dizer que isto tinha um nome, mas não sei qual é. De qualquer forma é só um hackzito, mas que pode acelerar significativamente uma operação como a que o Nazgulled quer fazer, principalmente se o polinómio for de grau elevado.

EDIT: Parece que se chama Horner Scheme.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Eu não disse isso pcaldeira.

Eu queria usar uma fórmula se simplificasse alguma coisa, usar um polinómio não simplifica nada.

O que eu disse foi que preferia usar um switch em vez de um array, foi só isso que eu disse. E isso não tem nada a ver com o problema que esta neste tópico, é uma decisão minha para a minha aplicação, que não interessa para nada.

Logo, não há nada mais a explicar...

Agradeço a ajuda de todos mas não há nada mais a debater, pelo menos da minha parte.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora