24 svar
322 visningar
Roger Moore är nöjd med hjälpen
Roger Moore 10 – Fd. Medlem
Postad: 22 feb 2017 14:21

standardavvikelse


Hej,
Jag behöver returnera standardavvikelsen av en vektor med olika mätvärden.

Försöker med:

public double stdDev() {
double sd = 0;

for (int n=1; n<x.length; n++)
{
sd = sd + Math.pow(x[n] - mean(), 2)/n;
}

double stdDev = Math.sqrt(sd);


return stdDev;
}

 

Där jag redan har gjort en fungerande metod för mean och för att skapa en vektor. Detta ger helt fel värde. Kan någon hjälpa mig till rätta?

//Roger

dobedidoo 85
Postad: 22 feb 2017 14:26

Kan inte Java själv, men det ser ut som om du delar varje term du lägger till sd med n, som väl är räknaren i loopen?

dobedidoo 85
Postad: 22 feb 2017 14:27
dobedidoo skrev :

Kan inte Java själv, men det ser ut som om du delar varje term du lägger till sd med n, som väl är räknaren i loopen?

 Kan tänka mig att du ska ta bort det och istället göra double stdDev = Math.sqrt(sd/x.length);

PeterÅ 842
Postad: 22 feb 2017 14:29

Var kommer x[] ifrån?

dobedidoo 85
Postad: 22 feb 2017 14:34
PeterÅ skrev :

Var kommer x[] ifrån?

 Det är såklart också en relevant fråga!

Antar man att x[] faktiskt är definierad, då får man bestämma sig för om man vill dela med x.length eller, vilket är fallet ibland, x.length - 1. Beror på tillämpningen.

PeterÅ 842
Postad: 22 feb 2017 14:46 Redigerad: 22 feb 2017 14:49

Tror det ska se ut så här:

public double stdDev()
{
   double sd = 0;
   double meanValue = mean(x); // där mean() beräknar medelvärdet

  for (int n=1; n<x.length; n++) // förutsatt att x[] index är 1-baserad, annars int n=0; n<x.length-1
   {
     sd = sd + (x[n] - meanValue) * (x[n] - meanValue);
   }
  double stdDev = Math.sqrt(sd / x.length);
  return stdDev;
}

Henrik Eriksson 1405 – Fd. Medlem
Postad: 22 feb 2017 14:50

x ska säkert vara argument till stdDev.

PeterÅ 842
Postad: 22 feb 2017 14:57 Redigerad: 22 feb 2017 14:58

Japp, men x kan även vara globalt definierad: double x[];

Roger Moore 10 – Fd. Medlem
Postad: 22 feb 2017 15:00 Redigerad: 22 feb 2017 15:07
dobedidoo skrev :
PeterÅ skrev :

Var kommer x[] ifrån?

 Det är såklart också en relevant fråga!

Antar man att x[] faktiskt är definierad, då får man bestämma sig för om man vill dela med x.length eller, vilket är fallet ibland, x.length - 1. Beror på tillämpningen.

 Ja, den är definierad, som instansvariabel i klassen: private double [] x ; .


Roger Moore 10 – Fd. Medlem
Postad: 22 feb 2017 15:05

dobedidoo
Tack
Har provat så som du skrivit. Med sd/x.length men det ger fel värde.

PeterÅ
Tack
Det där ser ut att kunna fungera. Är det någon särskild mening man skriver ut (x[n] - meanValue) * (x[n] - meanValue) som en produkt istället för att använda sig av en exponent?
Tyvär får jag nu felmeddelande: mean() in Measurements cannot be applied to (double[])

Roger Moore 10 – Fd. Medlem
Postad: 22 feb 2017 15:07

Fast metoden mean() returnerar en double...

Roger Moore 10 – Fd. Medlem
Postad: 22 feb 2017 15:10

Det är denna rad som ger kompileringsfel: double meanValue = mean(x); // där mean() beräknar medelvärdet

PeterÅ 842
Postad: 22 feb 2017 15:11

Anledningen är att det är tydligare och det är lättare att felsöka. Dessutom tror jag att multiplikation av två tal är effektivare (snabbare) än Math.Pow().

Visa mig definitionen på mean() och ditt anrop dit med x som argument.

dobedidoo 85
Postad: 22 feb 2017 15:14
PeterÅ skrev :

Tror det ska se ut så här:

public double stdDev()
{
   double sd = 0;
   double meanValue = mean(x); // där mean() beräknar medelvärdet

  for (int n=1; n<x.length; n++) // förutsatt att x[] index är 1-baserad, annars int n=0; n<x.length-1
   {
     sd = sd + (x[n] - meanValue) * (x[n] - meanValue);
   }
  double stdDev = Math.sqrt(sd / x.length);
  return stdDev;
}

Angående  for-loopen: Borde det inte vara antingen

for (int n=1; n<=x.length; n++)  // om x[] är 1-baserad (dvs. <= i.st.f. bara <)

eller

for (int n=0; n<x.length; n++) // om x[] är 0-baserad (dvs. bara <)

?

Roger Moore 10 – Fd. Medlem
Postad: 22 feb 2017 15:14
PeterÅ skrev :

Anledningen är att det är tydligare och det är lättare att felsöka. Dessutom tror jag att multiplikation av två tal är effektivare (snabbare) än Math.Pow().

Visa mig definitionen på mean() och ditt anrop dit med x som argument.

 Jag förstår :)


public double mean() {
double sum = 0;
int i = 0;
for (i=0; i<x.length; i++) {
sum+=x[i];
}
return sum/counter;
}

dobedidoo 85
Postad: 22 feb 2017 15:16
Roger Moore skrev :

dobedidoo
Tack
Har provat så som du skrivit. Med sd/x.length men det ger fel värde.

Kanske summeringen i for-loopen blir för "kort" (enligt min förra post) och/eller så ska det delas med x.length - 1 (finns två varianter av standardavvikelsen, och vilken som är "bäst" beror på tillämpning).

PeterÅ 842
Postad: 22 feb 2017 15:18

Det ska vara
return sum/x.length;

PeterÅ 842
Postad: 22 feb 2017 15:27 Redigerad: 22 feb 2017 15:35

En sak till:

Array Index i Java startar från 0. Därför ska dina loopar se ut så här när de hanterar x[]

for (i = 0;  i < x.length; i++) Loopen startar med 0 och stannar när i = 9. Antal = 10

Med 1-baserad index blir det istället (ex. vis. Visual Basic)
for (i = 1;  i <= x.length; i++) Loopen startar med 1 och stannar när i = 10. Antal = 10

Om du har 10 tal i x har de index 0-9 (=10 st) ELLER 1-10. Det är viktigt att du har koll på detta för du får ett sk. run time error om du använder ett indexvärde för x som inte finns.

Roger Moore 10 – Fd. Medlem
Postad: 22 feb 2017 15:36

dobedidoo: Har provat båda varianterna :/

PeterÅ: La nyss märke till det! Jag har ändrat fram och tillbaka en stund nu och det är därför det såg tokigt ut. Har för övrigt ändrat till sum/x.length men det löser inte kompileringsfelet :/

PeterÅ 842
Postad: 22 feb 2017 15:41

Aha! Du har ju x som klassmedlem. Ändra
 double meanValue = mean(x);
till
 double meanValue = mean();

PeterÅ 842
Postad: 22 feb 2017 15:45

Observera också att du måste ändra i funktionen public double stdDev() 
från:
for (int n = 1; n < x.length; n++) 
till:
for (int n = 0;  n < x.length; n++) 

Roger Moore 10 – Fd. Medlem
Postad: 22 feb 2017 15:54
PeterÅ skrev :

Aha! Du har ju x som klassmedlem. Ändra
 double meanValue = mean(x);
till
 double meanValue = mean();

 Tack för alla svar!
Jo PeterÅ men när jag gjorde sådär så fick jag samma värde som jag fick i början (när jag inte använde for (i=0...) och inte (i=1...) naturligtvis).
Jag har nu äntligen lyckats få fram korrekt svar men det lite underliga är att jag gjorde det genom att byta ut alla x.length mot counter (även i mean()-metoden).
Jag undrar varför det inte gick med x.length? Jag har en interaktionsruta där jag kan testa och skapa objekt osv. Om jag skapar en vektor m och sedan skriver m.length; så fungerar inte det heller. Varför?

Roger Moore 10 – Fd. Medlem
Postad: 22 feb 2017 15:58
Roger Moore skrev :
PeterÅ skrev :

Aha! Du har ju x som klassmedlem. Ändra
 double meanValue = mean(x);
till
 double meanValue = mean();

 Tack för alla svar!
Jo PeterÅ men när jag gjorde sådär så fick jag samma värde som jag fick i början (när jag inte använde for (i=0...) och inte (i=1...) naturligtvis).
Jag har nu äntligen lyckats få fram korrekt svar men det lite underliga är att jag gjorde det genom att byta ut alla x.length mot counter (även i mean()-metoden).
Jag undrar varför det inte gick med x.length? Jag har en interaktionsruta där jag kan testa och skapa objekt osv. Om jag skapar en vektor m och sedan skriver m.length; så fungerar inte det heller. Varför?

Tror jag vet varför... Jag har en metod som ökar storleken på vektorn när jag matat in för många värden. Men jag vill ju bara använda mig av de värden jag matat in, alltså är längden length för lång. Vad dum jag känner mig -_-

PeterÅ 842
Postad: 22 feb 2017 16:04

Utmärkt att du själv hittade felet. Rent generellt tror jag du ska minska på globala (klass)-variabler.
Framförallt ska funktionerna ha argument istället för som du gör nu. Ett bra exempel är mean().
Skriv om den funktionen för att ta en variabel som argument:
double mean(double d)
Fördelen är att den kan användas rent generellt och inte bara för din x[] samt att felsökning i alla fall inte blir svårare.

Roger Moore 10 – Fd. Medlem
Postad: 22 feb 2017 16:07
PeterÅ skrev :

Utmärkt att du själv hittade felet. Rent generellt tror jag du ska minska på globala (klass)-variabler.
Framförallt ska funktionerna ha argument istället för som du gör nu. Ett bra exempel är mean().
Skriv om den funktionen för att ta en variabel som argument:
double mean(double d)
Fördelen är att den kan användas rent generellt och inte bara för din x[] samt att felsökning i alla fall inte blir svårare.

 Tack för tipset! Ska ändra på det! :)

Svara Avbryt
Close