[C#] probleem met recursie?

Pagina: 1
Acties:

  • ungarmax
  • Registratie: December 2001
  • Laatst online: 29-06-2021
Ik ben al een tijdje bezig een fractal te maken volgens de formule f(z)=z^2 + p.
het is de bedoeling dat ik voor elke pixel coordinaat een functie bereken en dan probeer te zien of het reele deel of het imaginaire deel buiten een bepaald straal komt te liggen.(in dit geval 1 of 2)

f(z)=z^2 + p
z= a+bj, dus z^2 levert dus (a+bj)(a+bj)=((a*a)-(b*b)) + ((b*a)+(a*b))j
p= c+dj maar is pixel afhankelijk dus: p=px+pyj we vermenigvuldigen px en py met een geschikte waarde om binnen het bereik van het venster te blijven.
in dit geval (omdat mijn venster zo groot is) px*(1/354) en py*(1/333).
Je krijgt dat een reel deel:
FZNreel=((az*az)-(bz*bz))+ (x*(1/354));
en een formule voor het imaginaire deel:
FZNimaginair=((bz*az)+(az*bz))+ (y*(1/333));

volgens mij gaat het fout in het onderste gedeelte van de code die ik voor het gemak maar even gedeeltelijk heb geplaatst.

code:
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
public void berekenKleur()
{
//bepaal nieuw startpunt z0, een getal tussen de 0 en de 1
Random randomGetal1 = new Random();
Random randomGetal2 = new Random();
az=randomGetal1.NextDouble();
bz=randomGetal2.NextDouble();

for (y=0; y<=333; y++)//doorloop alle pixel coordinaten
 {
    for (x=0; x<=354; x++)
    { 
    //maak de teller van het aantal recursieve aanroepen weer nul
    i=1;
    start:
    
    //bereken het reele en imaginaire deel van F(Zn)
    FZNreel=((az*az)-(bz*bz))+ (x*(1/354));       
    FZNimaginair=((bz*az)+(az*bz))+ (y*(1/333));  

    //controleer of het maximale aantal van i is bereikt, of dat het reele deel
    //of het imaginaire deel groter is geworden dan de straal van de cirkel(2)
    
   if((FZNreel > straal )|(FZNimaginair > straal)|(i > 55)  )
   {  
       //vul het array met waarden van de recursieve aanroepen (i). 
       //uit dit array lezen we later de waarden terug en kunnen we zo bepalen
       //welke kleuren de pixels moeten krijgen. b.v. als i < 15 pixel is geel
       //als i >=15 & <25 blauw, als i >55 zwart. (dat idee)
       aKleurArray[x,y] = i;
       //initialiseer az en bz opnieuw met dezelfde z0 waarde als de eerste pixel
       az=temp_az;
       bz=temp_bz;
   }//end if
            

   //als dat allemaal nog niet het geval is dan moet de functie opnieuw    
   //worden aangeroepen. 
   else
   {
       i=i+1;
       az=FZNreel;          
       bz=FZNimaginair; 
       goto start;
   }//end if

}//end for
}//end for
}//end berekenPixelKleur


Het echte probleem is dat wanneer ik het programma start, hij de berekeningen uitvoert en het hele scherm geel maakt (dat betekend dat voor alle pixels direct na 1 aanroep van de functie het reele deel of het imaginaire deel groter is geworden dan de straal, of hij tekent het hele scherm zwart; wat betekend dat het aantal recursieve aanroepen groter is geworden dan 55.
heeft iemand enig idee waarom er geen middenweg in deze code zit? volgens de theorie zou de cirkel verlaten moeten worden na een willekeurig aantal recursieve aanroepen. oftewel: er zouden iig een flink aantal pixels moeten zijn met verschillende kleuren, en niet het hele scherm met 1 kleur.
----edit---
thx!

[ Voor 33% gewijzigd door ungarmax op 29-10-2004 15:17 ]


  • cowgirl
  • Registratie: November 2000
  • Laatst online: 18-12-2025
ungarmax schreef op 29 oktober 2004 @ 13:41:
hmm lay-out is niet wat ik wenste..iemand ff snel wat hulp?
Code-tags tussen blokhaken zetten.

Verder kan ik je helaas niet helpen.

Verwijderd

De code is erg onleesbaar maar volgens mij gaat het mis omdat je az en bz niet opnieuw initialiseert. Als je uit de loop breekt omdat "(FZNreel > straal )|(FZNimaginair > straal)|(i > 55)" dan geef je de huidige pixel een kleur. Vervolgens gaat de berekening verder met de volgende loop-waarde van x (of y) maar az en bz blijven dezelfde waarde houden.

Maar om meer duidelijkheid te krijgen zal je eerst de code even volledig moeten laten zien in een fatsoenlijke opmaak (Zie vorige post)
edit:
Je hebt de opmaak aangepast zie ik...

[ Voor 12% gewijzigd door Verwijderd op 29-10-2004 14:14 ]


Verwijderd

Nog een opmerking. Het is niet echt een recursief proces maar het is een iteratief proces. Je blijft de berekening herhalen, waarbij je de uitkomst weer als input gebruikt, totdat je aan bepaalde voorwaarden hebt voldaan.

Jouw "goto start" constructie verdient geen schoonheidsprijs (alhoewel hij wel zal werken). Je kan hier gewoon een do-while loop van maken. Maakt de code wat doorzichtiger en leesbaarder.

B.T.W. Ik zie dat az en bz helemaal niet initialiseert worden. Ik dacht (maar weet niet zeker) dat de startwaarde van az en bz afhankelijk is van x en y. Bij een madelbrot fractal is dat in ieder geval wel het geval.

[ Voor 27% gewijzigd door Verwijderd op 29-10-2004 14:20 ]


  • ungarmax
  • Registratie: December 2001
  • Laatst online: 29-06-2021
Verwijderd schreef op 29 oktober 2004 @ 14:12:
Nog een opmerking. Het is niet echt een recursief proces maar het is een iteratief proces. Je blijft de berekening herhalen, waarbij je de uitkomst weer als input gebruikt, totdat je aan bepaalde voorwaarden hebt voldaan.

Jouw "goto start" constructie verdient geen schoonheidsprijs (alhoewel hij wel zal werken). Je kan hier gewoon een do-while loop van maken. Maakt de code wat doorzichtiger en leesbaarder.

B.T.W. Ik zie dat az en bz helemaal niet initialiseert worden. Ik dacht (maar weet niet zeker) dat de startwaarde van az en bz afhankelijk is van x en y. Bij een madelbrot fractal is dat in ieder geval wel het geval.
Je hebt gelijk wat betreft de schoonheids prijs! :)
ik gebruik dit ook niet, ik heb een methode die dit hele proces verwerkt, maar ik dacht om het ff duidelijk te maken gebruik ik even een goto.

Wat betreft de startwaarden;
je kan inderdaad de startwaarden afhankelijk laten zijn van x en y maar in de opdracht wilde ik proberen om "p" van de pixels afhankelijk te laten zijn.

Hoe bedoel je trouwens az en bz worden niet geinitialiseerd?
Als je bedoeld het aanmaken-->Ik heb ze aangmaakt in het begin van de klasse double az; en double bz; maar ik dacht laat ik dat maar niet laten zien vanwege de ellenlange tekst die je dan krijgt.

volgens mij initialiseer ik az en bz trouwens opnieuw door: az=FZNreel; en bz=FZNimaginair; maar dat kan ik mis hebben (want hij werkt niet goed he ;) )

Verwijderd

ungarmax schreef op 29 oktober 2004 @ 14:25:
[...]

volgens mij initialiseer ik az en bz trouwens opnieuw door: az=FZNreel; en bz=FZNimaginair; maar dat kan ik mis hebben (want hij werkt niet goed he ;) )
Dat klopt, maar dat doe je alleen als de randvoorwaarden nog niet bereikt zijn en je de functie nog een keer laat doorrekenen.

Als de randvoorwaarden wel bereikt worden (dat grote if statement) dan bewaar je het aantal iteraties (i) in je kleurenarray. az en bz behouden echter hun huidige waarde. Met deze waarden van az en bz ga je weer verder rekenen. En omdat az en bz niet veranderen en x en y maar een heel klein beetje zal de uitkomst van je berekening weer ongeveer hetzelfde zijn. Daardoor zal waarschijnlijk de test "(FZNreel > straal )|(FZNimaginair > straal)" ook weer True zijn.... enz. enz.

Je moet in ieder geval az en bz weer initialiseren. Als je ze niet van x en y wil laten afhangen zal je ze waarschijnlijk 0 (nul) moeten maken.

[edit]
Ik zie dat je code iets hebt aangepast. Als je een beetje wil testen is het handiger om az en bz te initialiseren met een constante i.p.v. een random waarde. Dan kan je tenminste je programma aan aantal keren laten draaien met steeds hetzelfde resultaat. D'as handiger met fouten zoeken :Y)

[ Voor 14% gewijzigd door Verwijderd op 29-10-2004 14:41 ]


  • ungarmax
  • Registratie: December 2001
  • Laatst online: 29-06-2021
Ik heb nu de code veranderd zoals het nu is in de eerste post.
Het hele scherm is nu gespikkeld en wel zwart en geel. :)
dus niet meer helemaal zwart. (dus we zijn al verder :*) )
nu rest de vraag nog waarom hij zo springt tussen de minimale waarde en de maximale waarde.

[ Voor 87% gewijzigd door ungarmax op 29-10-2004 14:42 ]


  • DolleDries
  • Registratie: Oktober 2000
  • Laatst online: 10-05 11:59
Maak overal doubles van in plaats van combineren van ints en doubles.
80/100 = 0 in int termen en 0.8 in double termen.

  • ungarmax
  • Registratie: December 2001
  • Laatst online: 29-06-2021
ik heb eigenlijk overal doubles van gemaakt omdat ik juist met komma getallen werk.

alleen i, x, y en straal, zijn integers. maar het is ook niet nodig daar doubles van te maken omdat ze alleen maar tellen of een vaste waarde hebben.

Verwijderd

ungarmax schreef op 29 oktober 2004 @ 14:37:
[...]
nu rest de vraag nog waarom hij zo springt tussen de minimale waarde en de maximale waarde.
Verder moet je ook letten op wat Dolle Dries zei: Integers delen levert altijd een integer op.
b.v.
code:
1
x*(1/354)

1, 354 en x zijn Integers. 1/354 zal een Integer opleveren, 0 (nul) om precies te zijn. en x*0 is ook weer 0.
Waarschijnlijk gaat het zo beter:
code:
1
x*(1.0/354.0)

Op zulke zaken zul je erg moeten letten.

[edit]
Ho, stop je moet az en bz niet initialiseren met Random getallen. Geen wonder dat alles continue verspringt. Bij elke stap voor x en y moeten az en bz weer precies dezelfde beginwaarde hebben!

[ Voor 25% gewijzigd door Verwijderd op 29-10-2004 14:59 ]


  • ungarmax
  • Registratie: December 2001
  • Laatst online: 29-06-2021
Verwijderd schreef op 29 oktober 2004 @ 14:49:
[...]
1, 354 en x zijn Integers. 1/354 zal een Integer opleveren, 0 (nul) om precies te zijn. en x*0 is ook weer 0.
Op zulke zaken zul je erg moeten letten.
Auw!
jullie hebben inderdaad (weer) gelijk
thx! _/-\o_

Verwijderd

Even een nieuwe post voor de duidelijkheid:

Ho, stop je moet az en bz niet initialiseren met Random getallen. Geen wonder dat alles continue verspringt. Bij elke stap voor x en y moeten az en bz weer precies dezelfde beginwaarde hebben!

  • ungarmax
  • Registratie: December 2001
  • Laatst online: 29-06-2021
Ik heb dit er nu van gemaakt
code:
1
2
3
//initialiseer az en bz opnieuw met dezelfde z0 waarde als de eerste pixel
       az=temp_az;
       bz=temp_bz;


temp_az en temp_bz zijn doubles.
Zodra je op een knop bereken fractal drukt zal az0 en bz0 worden bepaald door een random waarde. deze waarde wordt direct doorgekoppeld naar temp_az en temp_bz zodat we die later weer kunnen gebruiken voor de tweede pixel.

Verwijderd

Dat lijkt me OK.
Echter, als je een beetje wil testen is het handiger om az en bz te initialiseren met een constante i.p.v. een random waarde. Dan kan je tenminste je programma aan aantal keren laten draaien met steeds hetzelfde resultaat. D'as handiger met fouten zoeken. Je kan dan beter zien wat de gevolgen zijn van aanpassingen in de berekeningen.

Veel succes. Ik ga nu aan aantal uurtjes off-line.

[ Voor 10% gewijzigd door Verwijderd op 29-10-2004 15:22 ]

Pagina: 1