Thema indholdsfortegnelse -- Tastaturgenvej: 'u'  Forrige tema i denne lektion -- Tastaturgenvej: 'p'  Næste slide i denne lektion -- Tastaturgenvej: 'n'Funktioner
13.  Eksempel: Rodsøgning

Vi gennemgår her et lidt mere avanceret eksempel, nemlig rodsøgning i en kontinuert funktion. Vores primære interesse er naturligvis problemløsning og funktioner, herunder topdown udvikling og programmering ved trinvis forfinelse.

13.1 Rodsøgning (1)13.2 Rodsøgning (2)
 

13.1.  Rodsøgning (1)
Indhold   Op Forrige Næste   Slide Aggregerede slides    Stikord Programindeks Opgaveindeks 

Vi starter med den essentielle observation, der danner baggrund for den centrale rodsøgningsalgoritme:

Enhver kontinuert funktion f, som har en negativ værdi i l og en positiv værdi i u (eller omvendt) vil have mindst én rod r mellem l og u.

Figur 13.1    En kontinuert funktion f med en rod mellem l og u

I figur 13.1 ser vi tydeligt at der skal være mindst én rod mellem l og u, nemlig i r. Der kan sagtens være flere rødder. Hvis dette er tilfældet har vi ingen egentlig kontrol over, hvilken af disse vi finder.

Ved at indsnævre intervallet [l, u], og ved hele tiden at holde roden mellem l og u, kan vi hurtigt finde frem til en værdi r for hvilken f(r) = 0.

 

13.2.  Rodsøgning (2)
Indhold   Op Forrige Næste   Slide Aggregerede slides    Stikord Programindeks Opgaveindeks 

Den central algoritme, som finder en rod mellem l og u er vist i program 13.1. Bemærk, at vi forudsætter at l er mindre end (eller lig med) u, og at fortegnet af funktionens værdi i l og u er forskellige. Med andre ord skal situationen være som i figur figur 13.1.

1
2
3
4
5
6
7
8
9
double findRootBetween(double l, double u){
 while (!isSmallNumber(f(middleOf(l,u)))){ 
   if(sameSign(f(middleOf(l,u)), f(u)))
     u = middleOf(l,u);
   else 
     l = middleOf(l,u);
 }
 return middleOf(l,u);
}
Program 13.1    Rodsøgningsfunktionen.

I programmet flytter vi gentagne gange enten l eller u til midtpunktet . Bemærk her, at l og u er parametrene i funktionen findRootBetween, og når vi ændrer på l eller u er det kun den lokale værdi i funktionen der ændres. Dette er en konsekvens af brug af værdiparametre (se afsnit 12.7).

De røde, blå og lilla dele af findRootBetween i program 13.1 skal nu programmeres. I alle tre tilfælde er der tale om småfunktioner, der medvirker til at højne abstraktionsniveauet i findRootBetween. I program 13.2 viser vi mulige definitionen af disse funktioner.

1
2
3
4
5
6
7
8
9
10
11
int sameSign(double x, double y){
  return x * y >= 0.0;
}

double middleOf(double x, double y){
  return x + (y - x)/2;
}

int isSmallNumber(double x){
  return (fabs(x) < 0.0000001);
}
Program 13.2    Funktionerne sameSign, middleOf og isSmallNumber.

Vi kan nu samle alle dele i ét program. Alternativt kunne vi have organiseret 'stumperne' i to eller flere kildefiler, ligesom vi gjorde i tændstikpige eksemplet i afsnit 11.5.

Vi bemærker, at vi i main programmerer en løkke, som gentagne gange beder brugeren af programmet om intervaller, hvor vi søger efter rødder i funktionen x3 - x2 - 41 x + 105. Som antydet ved vi at der er rødder i 5.0, 3.0 og -7.0. Det skyldes at x3 - x2 - 41 x + 105 faktisk bare er lig med (x - 5.0) . (x - 3.0) . (x + 7.0). Prøvekør selv programmet, og find rødderne!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <stdio.h>
#include <math.h>
 
double f (double x){
  /* (x - 5.0) * (x - 3.0) * (x + 7.0) */
  return (x*x*x - x*x - 41.0 * x + 105.0);
}

int sameSign(double x, double y){
  return x * y >= 0.0;
}

double middleOf(double x, double y){
  return x + (y - x)/2;
}

int isSmallNumber(double x){
  return (fabs(x) < 0.0000001);
}   

double findRootBetween(double l, double u){
 while (!isSmallNumber(f(middleOf(l,u)))){ 
   if(sameSign(f(middleOf(l,u)), f(u)))
     u = middleOf(l,u);
   else 
     l = middleOf(l,u);
 }
 return middleOf(l,u);
}  

int main (void){
    double x, y;
    int numbers; 

    do{
      printf("%s","Find a ROOT between which numbers: ");
      numbers = scanf("%lf%lf", &x, &y);

      if (numbers == 2 && !sameSign(f(x),f(y))){
          double solution = findRootBetween(x,y);
          printf("\nThere is a root in %lf\n", solution);
        }
      else if (numbers == 2 && sameSign(f(x),f(y)))
          printf("\nf must have different signs in %lf and %lf\n",
                  x, y);
      else if (numbers != 2)
          printf("\nBye\n\n");
    }
    while (numbers == 2);
}
Program 13.3    Hele rodsøgningsprogrammet.

Genereret: Onsdag 7. Juli 2010, 15:10:47
Thema indholdsfortegnelse -- Tastaturgenvej: 'u'  Forrige tema i denne lektion -- Tastaturgenvej: 'p'  Næste slide i denne lektion -- Tastaturgenvej: 'n'