Fetstil Fetstil Kursiv Understrykning linje färgläggning tabellverk Punktlista Nummerlista Vänster Centrerat högerställt Utfyllt Länk Bild htmlmode
  • Forum & Blog
    • Forum - översikt
      • .Net
        • asp.net generellt
        • c#
        • vb.net
        • f#
        • silverlight
        • microsoft surface
        • visual studio .net
      • databaser
        • sql-server
        • databaser
        • access
        • mysql
      • mjukvara klient
        • datorer och komponenter
        • nätverk, lan/wan
        • operativsystem
        • programvaror
        • säkerhet, inställningar
        • windows server
        • allmänt
        • crystal reports
        • exchange/outlook
        • microsoft office
      • mjukvara server
        • active directory
        • biztalk
        • exchange
        • linux
        • sharepoint
        • webbservers
        • sql server
      • appar (win/mobil)
      • programspråk
        • c++
        • delphi
        • java
        • quick basic
        • visual basic
      • scripting
        • asp 3.0
        • flash actionscript
        • html css
        • javascript
        • php
        • regular expresssion
        • xml
      • spel och grafik
        • DirectX
        • Spel och grafik
      • ledning
        • Arkitektur
        • Systemutveckling
        • krav och test
        • projektledning
        • ledningsfrågor
      • vb-sektioner
        • activeX
        • windows api
        • elektronik
        • internet
        • komponenter
        • nätverk
        • operativsystem
      • övriga forum
        • arbete karriär
        • erbjuda uppdrag och tjänster
        • juridiska frågor
        • köp och sälj
        • matematik och fysik
        • intern information
        • skrivklåda
        • webb-operatörer
    • Posta inlägg i forumet
    • Chatta med andra
  • Konto
    • Medlemssida
    • Byta lösenord
    • Bli bonsumedlem
    • iMail
  • Material
    • Tips & tricks
    • Artiklar
    • Programarkiv
  • JOBB
  • Student
    • Studentlicenser
  • KONTAKT
    • Om pellesoft
    • Grundare
    • Kontakta oss
    • Annonsering
    • Partners
    • Felanmälan
  • Logga in

Hem / Forum översikt / inlägg

Posta nytt inlägg


Fibonacci problem

Postades av 2005-12-12 10:40:20 - Robert Lundgren, i forum c++, Tråden har 27 Kommentarer och lästs av 1845 personer

Jag testade en version av Fibonacci som ser ut på följande sätt:

int fibonacci(int Tal) {
	int FibTal;

	FibTal = Tal;

	if (Tal == 0 || Tal == 1 ) 
		return Tal;
	else
		for(int i = 1;i == Tal;i++)
			FibTal = FibTal + i;

	return FibTal;
}


Problemet är att den inte plusar på i på FibTalet.

Dvs om Tal är 3 blir FibTal också 3.

Någon som har nån fundering?


Svara

Sv: Fibonacci problem

Postades av 2005-12-12 11:06:47 - Niklas Jansson

Det är knappast kompilatorn som har gjort fel. Till att börja med är det ett mycket ovanligt sätt att skriva Fibonacci-funktionen på, och fel på minst två sätt.

Bestäm dig först för om du vill köra med
1. en rekursiv variant
2. dynamisk programmering
3. en iterativ variant

Felen är:
1. for-satsen har ett == där det skall vara någon av !=, < eller <=.
2. Du kommer få "ackumulerade summan", snarare än Fibonaccitalet.


Svara

Sv:Fibonacci problem

Postades av 2005-12-12 12:38:42 - Robert Lundgren

det fungerade med att ändra == till < tack


Svara

Sv: Fibonacci problem

Postades av 2005-12-14 16:03:35 - Sam Borfors

Alternativt så kan man ju initiera FibTal till 0 i stället för till Tal, känns enklare att förstå vad som händer då. Se i övrigt Niklas kommentarer, framförallt hur fibonacci egentligen definieras:

F(n) = F(n-1) + F(n-2)
F(0) = 0
F(1) = 1


Svara

Sv:Fibonacci problem

Postades av 2005-12-15 17:45:40 - Per Persson

Den rekursiva varianten,

int F(int n)
{
    if (n == 0)
        return 0;

    if (n == 1)
        return 1;

    return F(n-1) + F(n-2);
}

är väldigt ineffektiv.

Betydligt effektivare är en enkel iterativ variant:
int F(int n)
{
    int x0 = 0, x1 = 1;
    int i;

    for (i=0; i<n; i++) {
        int x2 = x0 + x1;
        x0 = x1;
        x1 = x2;
    }

    return x0;
}


För stora n finns det en variant som är ännu effektivare. Den bygger på att den iterativa varianten egentligen utför vektor- och matrisberäkningen z = A^n z0, där z=(x0, x1), z0=(0, 1) och A=((0, 1), (1, 1)), samt att "upphöjt till" kan beräknas effektivt genom A^(2n) = (A^n)^2. Det blir mer avancerade beräkningar, så för små n lönar sig inte algoritmen.


Svara

Sv: Fibonacci problem

Postades av 2005-12-17 12:50:24 - Håkan Borneland

Kuriosa, appropå ingenting.
De flesta kompilatorer optimerar ändå den rekursiva lösningan till en WHILE loop.

//Håkan


Svara

Sv:Fibonacci problem

Postades av 2005-12-19 08:51:21 - Per Persson

Håkan... Jag tror du har fel. Enkelt rekursiva funktioner går bra att optimera till en iteration, men inte dubbelt rekursiva.

Om du tror annorlunda, visa gärna hur koden skrivs om. Visa eventuellt assembly.


Svara

Sv: Fibonacci problem

Postades av 2005-12-19 15:26:42 - Niklas Jansson

Tail-recursive går ju alltid att fixa, men går verkligen alla enkla anrop?
Vad blir då nånting i stil med följande?

int a(int n)
{
if(n==0)
return 0;
b;
c=a(n-1);
d;
return f(c, d);
}


Sen skulle ju en kompilator teoretiskt sett kunnna fixa en dubbel rekursion, om bara två koder är ekvivalenta...

EDIT: vad fan skriver jag...?
ändrade koden lite.


Svara

Sv: Fibonacci problem

Postades av 2005-12-20 22:47:02 - Håkan Borneland

Per och Niklas.

Syftar på en "enkel" rekursion enligt Pers exempel ovan, inget annat.

//Håkan


Svara

Sv:Fibonacci problem

Postades av 2005-12-20 23:13:39 - Niklas Jansson

Men rekursionen ovan är inte enkel; du gör två anrop till funktionen. Hur menar du att man skulle kunna optimera bort det?

(Naturligtvis går det ju teoretiskt sett, men i praktiken?)


Svara

Sv: Fibonacci problem

Postades av 2005-12-21 08:35:50 - Per Persson

Går det ens teoretiskt utan att införa en egen stack?


Svara

Sv: Fibonacci problem

Postades av 2005-12-21 10:32:45 - Håkan Borneland

<b>Niklas:</b> Nä precis (inte enkel) fort (läst) och fel (svar) blev det.
Så för klarhets skull så menar jag tail (enkel) rekursion.

<b>Per:</b> Tror du att en stack är den datastruktur som skulle kunna göra jobbet?
En trädstruktur (av något slag) känns mer rätt (OBS, spekulerar).
Men det ligger utanför mitt område, och du/ni har nog mer koll.
Läste inte läste kursen Compiler Construction (hade varit mycket intressant).

//Håkan


Svara

Sv:Fibonacci problem

Postades av 2005-12-21 12:09:08 - Martin Adrian

>Tror du att en stack är den datastruktur som skulle kunna göra jobbet?

Svansrekursionen är som sagts tidigare enkel att göra om till iteration men den första rekursionen behöver spara tillståndet och då behövs det en stack.

Quicksort fungerar på samma sätt med dubbel rekursion och där brukar man använda en stack.


Svara

Sv:Fibonacci problem

Postades av 2005-12-21 12:38:16 - Niklas Jansson

<b>>Går det ens teoretiskt utan att införa en egen stack?</b>
Med teoretiskt menar jag följande (obs, <b>mycket</b> teoretiskt =) ):

Vi har en funktion A som inte har några bieffekter utan för varje input x genererat ett specifikt output y.
Om vi nu kan konstruera en funktion B som inte heller har några sideffekter, och ändå genererar samma grejer (A(x)=B(x) för alla x), så är de ju ekvivalenta.

En "tillräckligt smart kompilator" (vilket sannolikt är mer eller mindre omöjligt) skulle ju därför kunna översätta A till B. A är den rekursiva och B är den iterativa.


Problemet här är ju stackstorlek, etc., och att dessa då i princip genererar sidoeffekter, men om vi tänker oss oändligt minne och oändligt stora int:ar, så...

(Jag inser naturligtvis att detta aldrig kommer att funka i praktiken, tro inget annat.)


Svara

Sv: Fibonacci problem

Postades av 2005-12-21 18:32:14 - Per Persson

Okej, men då handlar det om olika algoritmer. När man talar om att svansrekursion kan överföras i iteration handlar det i princip om samma algoritm, bara olika sätt att skriva den.


<b>Tror du att en stack är den datastruktur som skulle kunna göra jobbet?
En trädstruktur (av något slag) känns mer rätt (OBS, spekulerar).</b>

Jag förstår varför du tycker att en trädstruktur känns mer rätt, men kan inte se hur en sådan skulle kunna användas. Hur går man genom ett träd utan att använda rekursion?

En stack används varje gång en funktion anropas, t.ex. vid rekursion. För att få en iterativ kod kan man manuellt implementera det som kompilatorn och processorn utför vid rekursiva anrop, eller använda stacken på andra sätt, t.ex. för att lagra delresultat.


Svara

Sv:Fibonacci problem

Postades av 2005-12-21 19:50:07 - Niklas Jansson

<b>>Okej, men då handlar det om olika algoritmer. När man talar om att svansrekursion kan överföras i iteration handlar det i princip om samma algoritm, bara olika sätt att skriva den. </b>
Tja, det är ju en definitionsfråga. Om man tänker på något så enkelt som fakulteten, så utgår man ju från två (naturligtvis ekvivalenta) ekvationer; ena implementerar man iterativt, andra som rekursivt:

x(n)=n*(n-1)...

resp.

x(0) = 1
x(n) = n*x(n-1)

Visst, naturligtvis känns det som att det är i stort sett samma algoritm, men det är ju en gradfråga. Om två funktioner ger samma svar så är defintionerna ekvivalenta, och då är det ju i någon mening ekvivalenta algoritmer. Var går gränsen mellan ekvivalent och "samma" algoritm?


Svara

Sv: Fibonacci problem

Postades av 2005-12-22 08:33:14 - Per Persson

En lämplig definition av "samma algoritm" är att den ena kan överföras i den andra genom en serie enkla transformationer (där förstås mängden av tillåtna sådana transformationer måste definieras). Svansrekursion kan enkelt överföras i iteration, men att överföra F(n) = F(n-2) + F(n-1) till en iteration är jag tveksam till att det skulle gå.

Ovanstående ger vad jag vill kalla "ekvivalens av algoritmer". Att två algoritmer ger samma svar innebär bara att de implementerar samma funktion. Det är förvisso också en ekvivalensrelation, men inte av sådan art att jag vill säga att de utgör "samma" algoritm.

Jag anser att p0(n)=2*2*...*2 (n st) och p1(0) = 1, p1(n) = 2*p1(n-1) utgör samma algoritm, medan p2(0) = 1, p2(2n) = (p2(n))^2, p2(2n+1) = 2*p2(2n) utgör en annan algoritm. Alla tre implementerar dock samma funktion, 2^n (för n=0, 1, ...).


Svara

Sv:Fibonacci problem

Postades av 2005-12-22 13:56:11 - Niklas Jansson

Nu är vi visserligen inne på för frågeställningen löjligt teoretiska utläggningar, men;

<b>>(där förstås mängden av tillåtna sådana transformationer måste definieras)</b>
Och där är pudelns kärna. Det är alltså bara en gradfråga; vad är en "enkel transformation", var går gränsen mellan "samma" och "likadana".

För även om de är "samma" algoritm så är ju inte beskrivningarna av dem identiska, då hade vi inte sagt att det var två olika algoritmer (p0, p1) från början.

Det kan ju dras ner på väldigt mycket enklare nivå;
är 1+1 och 2 samma sak?
är 2+2 och 4 samma sak?
är 2*2 och 4 samma sak?
är 2^2 och 4 samma sak?
är 2^2 och (1+1)*2 samma?

Definitionsfråga, helt enkelt.


Svara

Sv: Fibonacci problem

Postades av 2005-12-22 18:49:19 - Per Persson

Självklart är det en definitionsfråga. Men de kriterier man skall ha när man väljer de tillåtna transformationerna är att de skall vara
1) uppenbara (enkelt att förstå och acceptera att de inte förändrar vad en algoritm implementerar),
2) generella (inte specifika för en liten mängd algoritmer),
3) å andra sidan inte för generella (att säga att två algoritmer får överföras i varandra om de implementerar samma funktion går fetbort).


Svara

Sv:Fibonacci problem

Postades av 2005-12-24 11:49:56 - Andreas Hillqvist

Borde inte en Tail-recursive funktion se ut

int fibonacci(int n)
{
    if (n == 0)
        return 0;
    if (n = 1) 
        return 1;
    return fib(n, 0, 1);
}

int fib(int a, int c, int d)
{
    if (a <= 1)
        return d

    return fib(a - 1, d, c + d)
}


Svara

Sv: Fibonacci problem

Postades av 2005-12-25 19:20:39 - Per Hultqvist

Intressant diskussion, hoppas inte jag avbryter den alltför mycket då jag av en händelse sitter jag med Mathschallenge.net och lurar på ett Fibonacci-problem och har där med viss framgång använt matris-metoden (som omnämndes ovan) så jag publicerar min kod här utifall att den gör någon nytta för någon. Koden använder sig av klassen BigInteger som finns hos The CodeProject (http://www.codeproject.com/csharp/BigInteger.asp) eftersom jag just nu söker efter ett specifikt Fibonaccital F(k) där k ligger runt 500 000, vilket resulterar i ett tal som är ca 120 000 siffror långt.

Tar gärna emot förslag på hur denna kan optimeras för det tar någon minut att räkna ut ett enda Fibonaccinummer just nu och jag har ingen aning om hur långt upp jag måste leta...

        private BigInteger Fibonacci(long n)
        {
            if (n < 2) return new BigInteger(n);
            BigInteger[,] matrix = new BigInteger[2, 2] { { new BigInteger(1), new BigInteger(1) }, { new BigInteger(1), new BigInteger(0) } };
            return PowerMatrix(matrix, n - 1)[0, 0];
        }

        private BigInteger[,] PowerMatrix(BigInteger[,] A, long n)
        {
            if (n == 1) return A;
            if (n % 2 == 0) return PowerMatrix(MultiplyMatrix2By2(A, A), n / 2);
            return MultiplyMatrix2By2(A, PowerMatrix(MultiplyMatrix2By2(A, A), (n - 1) / 2));
        }

        public static BigInteger[,] MultiplyMatrix2By2(BigInteger[,] A, BigInteger[,] B)
        {
            if (A.GetLength(0) != 2 || A.GetLength(1)!=2 || B.GetLength(0)!=2 || B.GetLength(1)!=2) throw new ArgumentException("Wrong dimensions!");

            BigInteger[,] result = new BigInteger[2,2];

            result[0, 0] = A[0, 0] * B[0, 0] + A[0, 1] * B[1, 0];
            result[0, 1] = A[0, 0] * B[0, 1] + A[0, 1] * B[1, 1];

            result[1, 0] = A[1, 0] * B[0, 0] + A[1, 1] * B[1, 0];
            result[1, 1] = A[1, 0] * B[0, 1] + A[1, 1] * B[1, 1];

            return result;
        }


[Edit: Insåg just nu att jag postade C#-kod i ett C++-forum. Sorry!]


Svara

Sv: Fibonacci problem

Postades av 2005-12-28 08:42:07 - Per Persson

Andreas, det räcker med

int fibonacci(int n)
{
    return fib(n, 0, 1);
}

int fib(int a, int c, int d)
{
    if (a == 0)
        return c;

    return fib(a - 1, d, c + d)
}

Genom en enkel transformation kommer man fram till en icke-rekursiv lösning:
int fib(int a, int c, int d)
{
    while (1) {
        if (a == 0)
            return c;

        int a_new = a - 1;
        int c_new = d;
        int d_new = c + d;

        a = a_new;
        c = c_new;
        d = d_new;
    }
}

som sedan kan stoppas in i den övre funktionen för att undvika alla former av anrop:
int fibonacci(int a)
{
    int c = 0;
    int d = 1;

    while (1) {
        if (a == 0)
            return c;

        int a_new = a - 1;
        int c_new = d;
        int d_new = c + d;

        a = a_new;
        c = c_new;
        d = d_new;
    }
}


Svara

Sv:Fibonacci problem

Postades av 2005-12-29 11:15:02 - Andreas Hillqvist

Låt mig börja med ett citat:
<info>"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil."</info>
- Tony Hoare

Jag har jobbat med Erlang(http://www.erlang.se/) det senaste halvåret. Erlang där det saknas möjlighet att iterera/"loopa". Samtligavariabler är Write once. Man iterera där genom rekusion.

Erlangs styrka är att det väldigt effektivt på concurrency, distrubuerat, osv. Utvecklat av ericsson.

En applikation som intressant är Yaws(http://yaws.hyber.org/) vilket är en webbserver med hög prestanda.

Så jag frågar mig, Vad vinner man på din variant? Är vinsten vär det fler rader kod som resulterar? Kan man inte se varje ytterligare rad kod som en potencielt felkälla?


Svara

Sv: Fibonacci problem

Postades av 2005-12-29 15:50:46 - Per Persson

Min första variant var väl ändå kortare och renare än ditt förslag?

De andra (mer utvecklade eller mer invecklade beroende på tycke) varianterna skrev jag med anledning av diskussionerna angående kompilatorers omskrivning av svansrekursiva funktioner till iteration (loopar). Jag hävdade aldrig att de var bättre.


Svara

Sv:Fibonacci problem

Postades av 2006-01-01 16:48:28 - Andreas Hillqvist

Ditt första exempel är kort och renare. Men det är inte Tail-recursive. Om man skall skriva rekursiva funktioner bör det helst vara Tail-recursive.

Fördelen med recursiva funktioner är att det ofta ger minder kod än vid iterationer. Ta till exempe sorteringsalgoritmer. Där den rekursiva varianten ofta innebär enklare kod.

Då jag tycker ditt första inlägg gav skenet av att recursivitet är ineffektivt. Ville jag med mitt inlägg poängtera att recursiva funktioner är bra rätt använt. Detta kanske jag gjorde något klumpoigt. Då jag inte är C/C++ kodare eller insatt i Fibonacci problemet.


Svara

Sv: Fibonacci problem

Postades av 2006-01-01 18:24:59 - Per Persson

Skulle inte

int fibonacci(int n)
{
    return fib(n, 0, 1);
}

int fib(int a, int c, int d)
{
    if (a == 0)
        return c;

    return fib(a - 1, d, c + d)
}

vara svansrekursiv?


Svara

Sv:Fibonacci problem

Postades av 2006-01-01 23:52:20 - Andreas Hillqvist

Jag syftade på ditt första exempel:

<b>Den rekursiva varianten,</b>

int F(int n)
{
    if (n == 0)
        return 0;

    if (n == 1)
        return 1;

    return F(n-1) + F(n-2);
}

<b>
är väldigt ineffektiv.
</b>

Det andra exempel är jag nöjd med. Inget att klaga på.


Svara

Sv: Fibonacci problem

Postades av 2006-01-02 06:56:56 - Per Persson

Ah, okej. Rekursion i sig är inte ineffektivt, men <b>för fibonaccitalen</b> är det mycket ineffektivt att använda den "dubbelt rekursiva" implementationen.


Svara

Nyligen

  • 14:24 CBD regelbundet?
  • 14:23 CBD regelbundet?
  • 14:22 Har du märkt några verkliga fördel
  • 09:09 Vill du köpa medicinska tester?
  • 12:47 Vem beviljar assistansen – kommune
  • 14:17 Någon med erfarenhet av hemstädnin
  • 14:14 Bör man använda sig av en båtförme
  • 14:12 Finns det någon intressant hundblo

Sidor

  • Hem
  • Bli bonusmedlem
  • Läs artiklar
  • Chatta med andra
  • Sök och erbjud jobb
  • Kontakta oss
  • Studentlicenser
  • Skriv en artikel

Statistik

Antal besökare:
Antal medlemmar:
Antal inlägg:
Online:
På chatten:
4 569 617
27 953
271 709
5 740
0

Kontakta oss

Frågor runt konsultation, rådgivning, uppdrag, rekrytering, annonsering och övriga ärenden. Ring: 0730-88 22 24 | pelle@pellesoft.se

© 1986-2013 PelleSoft AB. Last Build 4.1.7169.18070 (2019-08-18 10:02:21) 4.0.30319.42000
  • Om
  • Kontakta
  • Regler
  • Cookies