Sábado, 7 de Junho de 2008

Variância em Smalltalk

Squeak Já que o artigo sobre variância rendeu outro artigo interessante, me empolguei e resolvi escrever como implementar o cálculo da variância em Smalltalk.

Como gostei muito da ferramenta e para privilegiar seu foco educacional, vou usar o Squeak.

Abra o System Browser e, se não tiver o pacote Kodumaro, crie-o. Crie então a categoria Kodumaro-Variance.

Crie então a seguinte classe:
FloatArray subclass: #VariantiableArray
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Kodumaro-Variance'


Agora os métodos…

Na categoria math functions, crie o método rms:
rms
"Calculates and returns the root mean square"
| aux |

aux := 0.
self do: [ :e |
aux := aux + (e * e)
].

↑ (aux / self size) sqrt


É claro que poderíamos criar um método para retornar o numerador do cálculo, mas vou fazer diferente. =)

Vamos implementar a variância populacional com média aritmética – average, herdado de Collection, já que costuma ser um valor mais redondo – e a variância da amostra com média quadrada, ambas também na categoria math functions.
populationalVariance
"Calculates and returns the populational variance"
| aux mean |

aux := 0.
mean := self average.

self do: [ :e | | temp |
temp := e - mean.
aux := aux + (temp * temp).
].

↑ aux / self size


Agora a variância amostral:
sampleVariance
"Calculates and returns the sample variance"
| aux mean |

aux := 0.
mean := self rms.

self do: [ :e | | temp |
temp := e - mean.
aux := aux + (temp * temp).
].

↑ aux / (self size - 1)


Está pronto!

Como assim? Só isso?

É, só isso. =)

Vamos testar, abra um Workspace e digite:
| v |

v := VariantiableArray newFrom: #(1 2 3 4 5).

Transcript
open;
show: 'Média aritmética: ', v average printString; cr;
show: 'Média quadrada: ', v rms printString; cr;
show: 'Variância populacional: ', v populationalVariance printString; cr;
show: 'Variância da amostra: ', v sampleVariance printString; cr.


Pressione M-a M-d para executar.

[]'s
Cacilhas, La Batalema

2 comentários:

Tiago Albineli Motta disse...

Smaltalk será o próximo target, assim que terminar meus estudos com ruby.

La Batalema Pitonisto disse...

O mesmo código em Io:

VariantiableList := Object clone do(
    elements := List

    asString := method(elements join(", "))

    average := method(elements average)

    populationalVariance := method(
        mean := average
        sum := 0
        elements foreach(e,
            aux := e - mean
            sum = sum + (aux * aux)
        )
        return sum / elements size
    )

    rms := method(
        sum := 0
        elements foreach(e,
            sum = sum + (e * e)
        )
        return (sum / elements size) sqrt
    )

    sampleVariance := method(
        mean := rms
        sum := 0
        elements foreach(e,
            aux := e - mean
            sum = sum + (aux * aux)
        )
        return sum / (elements size - 1)
    )
)

Salve como VariantiableList.io e teste o script abaixo:

Importer FileImporter import("VariantiableList")

a := VariantiableList clone do(
    elements = list(1, 10, 100, 1000)
)

"Lista: " print
 a println
"Média aritmética: " print
a average println
"Média quadrada: " print
a rms println
"Variância populacional: " print
a populationalVariance println
"Variância da amostra: " print
a sampleVariance println

[]'s
Cacilhas, La Batalema