# Fibonacci-Folge status Leiste.



## Dagobert (2. Apr 2007)

Ich habe ein Programm geschrieben womit man die Fibonacci-Folge einer Zahl berechnen kann...

da dies durchaus länger dauer kann wollte ich ein Progressbar mit Statusanzeige einbauen... leider sind bis jetzt alle versuche fehlgeschlagen... kann mir wohl jemand einen ansazt geben wie ich eien korrekt laufende ProgressBar hinbekomme.

Also hier schonmal meine Idee... 

ich habe eine Progreesbar die von 0 bis 100 geht
dann habe ich ein sleep drin... aber da weis ich nicht die passende zeit die ich einsetzen muss  :?: 
dann wird meine Bar um 1 geupdatet

ist das soweit inordnung? und was muss ich als Zeit für sleep reinpacken?

mfg
Dagobert


----------



## The_S (2. Apr 2007)

Nein, garantiert nicht. Du musst an bestimmten Punkten der Berechnung die ProgressBar updaten, sonst ist die Fortschrittsanzeige ja vollkommen falsch ...


----------



## Dagobert (2. Apr 2007)

ok thx...

kannst du mir bittte sagen wo ich bei ner Fib-Folge diese Punkte sind, denn ich weis es echt nicht so ganz...

hier ist mein code zum berechnen der fib...

```
private int berechnenFib(int n) {
		if (n == 0 || n == 1) {
			return n;
		} else {
			return (berechnenFib(n - 1) + berechnenFib(n - 2));
		}
	}
```


----------



## SlaterB (2. Apr 2007)

wenn du nicht weißt, wie lange deine Berechnung dauert,
dann kannst du logischereise auch keine Forschrittsanzeige machen..

kannst nebenbei einen Thread laufen lassen, der Sekunden hochzählt

--------

bei so ner Rekursion ist es allgemein möglich: 
berechne(n-1) von der Ausgangszahl,
dann hast du grob 50% der Arbeit, dann (n-2)

für feinere Unterteilung musst du eben in ein paar Ebenen tiefer den Zwischenstand anzeigen

-----
wie lange dauert  überhaupt diese Berechnung? wie speicherst du eine so große Zahl,
die länger als ein Blinzeln in der Berechnug dauert?
doch wohl nicht in einem int?


----------



## Dagobert (2. Apr 2007)

speichern XD

gar nicht wird mit return in int format zurückgegeben

habs jetzt mal auf Long geändert...

ok soweit so gut... ich muss also in der Rekusion bei jeden neuaufruf meine bar updaten.... aber um was für ein Wert? ich kann den counter wohl schlecht um 1 eínfach hochzählen.... denn dann kommen ein par Prozdent mehr als möglich aus... XD


----------



## SlaterB (2. Apr 2007)

solange du nicht weiß, wie man eine Bar grundsätzlich bedient,
muss man hier nicht weiterreden,
habe mich von Anfang an schon gewundert was wohl Fibonacci hier soll..

http://www.java2s.com/Code/Java/Swing-JFC/ProgressBar.htm


----------



## Dagobert (2. Apr 2007)

ich weis wie ich so eine bar bedienen, ich weis nur nicht an welcher stelle ich sie im rekusiven aufruf updaten soll -.-
bzw. mit welchen wert


----------



## The_S (2. Apr 2007)

Da du nciht weißt, wie viele durchläufe du benötigst, kannst du auch keinen normalen Fortschrittsbalken einbauen. Als alternative wäre ein simpler WorkInProgress balken, der dem User anzeigt, dass zumindest noch was gemacht wird. 

Ich war mal so frei:


```
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

import javax.swing.JComponent;
import javax.swing.JFrame;

public class WorkInProgress extends JComponent{

	private static final long serialVersionUID = 1L;
	
	private int speed = 50;
	private int pos = 0;
	private int step = 4;
	private boolean workInProgress = false;
	
	private String progressText = null;
	private String noProgressText = null;
	private BufferedImage status = null;
	
	public WorkInProgress() {
		
		progressText = "Work in Progress";
		noProgressText = "Nothing in Progress";
		status = new BufferedImage(73, 20, BufferedImage.TYPE_INT_ARGB);
		setForeground(Color.red);
		setBackground(Color.WHITE);
		setFont(new Font("monospaced", Font.BOLD + Font.ITALIC, 11));
		Graphics2D g2d = status.createGraphics();
		g2d.setColor(Color.BLACK);
		for (int i = 0; i < 5; i++) {
			g2d.fillRect(15 * i, 3, 14, 14);
		}
		g2d.dispose();
	}
	
	private void checkProgress() {
		
		new Thread(new Runnable() {
			public void run() {
				boolean leftToRight = true;
				while (isWorkInProgress()) {
					repaint();
					if (leftToRight) {
						pos += step;
						if (getWidth() - status.getWidth() < pos) {
							leftToRight = false;
						}
					}
					else {
						pos -= step;
						if (pos <= 0) {
							leftToRight = true;
						}
					}
					try { 
						Thread.sleep(speed);
					}
					catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				pos = 0;
				repaint();
			}
		}).start();
	}
	
	public void paintComponent(Graphics g) {
		
		String drawString = null;
		g.setColor(getBackground());
		g.fillRect(0, 0, getWidth(), getHeight());
		g.setColor(getForeground());
		g.setFont(getFont());
		if (isWorkInProgress()) {
			drawString = progressText;
			g.drawImage(status, pos, getHeight() / 2 - status.getHeight() / 2, this);
		}
		else {
			drawString = noProgressText;
		}
		int w = g.getFontMetrics(g.getFont()).stringWidth(drawString);
		int h = g.getFontMetrics(g.getFont()).getHeight();
		g.drawString(drawString, getWidth() / 2 - w / 2, getHeight() / 2 + h / 4);
	}

	public int getSpeed() {
		return speed;
	}

	public void setSpeed(int speed) {
		this.speed = speed;
	}

	public boolean isWorkInProgress() {
		return workInProgress;
	}

	public void setWorkInProgress(boolean workInProgress) {
		this.workInProgress = workInProgress;
		if (isWorkInProgress()) {
			checkProgress();
		}
	}

	public String getNoProgressText() {
		return noProgressText;
	}

	public void setNoProgressText(String noProgressText) {
		this.noProgressText = noProgressText;
	}

	public String getProgressText() {
		return progressText;
	}

	public void setProgressText(String progressText) {
		this.progressText = progressText;
	}

	public BufferedImage getStatus() {
		return status;
	}

	public void setStatus(BufferedImage status) {
		this.status = status;
	}

	public int getStep() {
		return step;
	}

	public void setStep(int step) {
		this.step = step;
	}
	
	public static void main(String[] args) {
		
		JFrame frame = new JFrame();
		frame.setSize(200, 50);
		WorkInProgress wip = new WorkInProgress();
		frame.add(wip);
		frame.setVisible(true);
		wip.setWorkInProgress(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
}
```

Zum Testen direkt ausführbar ...


----------



## Dagobert (2. Apr 2007)

ok thx 

ich werde nachher mal reinschauen ob ichs verstehe


----------



## The_S (2. Apr 2007)

Da gibts nix zu verstehen, du ersetzt deine ProgressBar einfach durch diese Componente und rufst anschließend setWorkInProgress(true) auf  .


----------



## Roar (2. Apr 2007)

erhöhe doch für jede berechnete zahl den wert deiner bar um 1, voraussetzung ist natürlich dass du den maximalwert der bar auf den  wert der zu berechnenden werte gesetzt hast.
bei *deiner* fib implementierung hast du dann auch genug zu gucken für eine zahl im integer bereich


----------



## Leroy42 (2. Apr 2007)

Vergiß es!

Mit den Informationen alleine, die deine rekursive Funktion hergibt,
wirst du nie die Gesamtzeit _erkennen_ können, die du ja
für eine Fortschrittsanzeige benötigst, ohne den Fibonacci-Wert selbst
zuvor berechnet zu haben.

Was eventuell ginge, wäre eine Bezugnahme auf den Gesamtwert,
indem du ihn dir _in situ_ berechnest.







Aber auch das wäre unverhältnismäßig kompliziert,
und würde deiner Idee grundsätzlich widersprechen.


----------



## SlaterB (2. Apr 2007)

eine Progressbar muss doch nicht genau sein,
und auch nicht die Endzeit schon am Anfang anzeigen

was spricht dagegen, für die 8 höchsten Rekursionsschritte je eine Zeit von 1/8 anzunehmen?
wenns länger dauert, dann eben mehr Schritte,
kann man ja grob an der Ausgangszahl abschätzen


----------



## Leroy42 (2. Apr 2007)

SlaterB hat gesagt.:
			
		

> was spricht dagegen, für die 8 höchsten Rekursionsschritte je eine Zeit von 1/8 anzunehmen?



Ach ja!?

Dann zeig' doch mal wie Dagobert *das* in seine Fibbonacci-Methode einbauen soll.

```
private int berechnenFib(int n) { 
      if (n == 0 || n == 1) { 
         return n; 
      } else { 
         return (berechnenFib(n - 1) + berechnenFib(n - 2)); 
      } 
   }
```

Viel Spaß!   

Das Problem ist doch, daß diese Methode, je Aufruf, nur
die Information über das aktuelle _n_ besitzt.


----------



## SlaterB (2. Apr 2007)

ja, 5 Min. programmieren muss man schon 
z.B. eine zweite 20-zeilige Operation, die einen Tiefen-Parameter mitbekommt + Grenze,
ab dieser Grenze wird die normale Operation aufgerufen,
so dass so gut wie kein Overhead entsteht

ist für einen Anfänger nicht leicht, aber 'vergiss es' klingt so fundamental, 
als wenn das grundsätzlich dem Rekursionsprinzip widerspricht,
dabei ein Klacks

edit: baut natürlich immer noch auf der Grundannahme eines binären Baums mit gleicher Suchzeit für jeden Teilbaum auf,
sonst schwieriger, stimmt,
aber Exemplarvariablen gibts dann auch noch..


----------



## Roar (2. Apr 2007)

wieso soll die progressbar denn immer gleichschnell fortschreiten? 
je lägner die operation, desto langsamer der balken: it's not a bug it's a feature


----------



## Leroy42 (2. Apr 2007)

SlaterB hat gesagt.:
			
		

> ja, 5 Min. programmieren muss man schon



Dann bitte ich dich hiermit ganz offiziell, diese 5++ Minuten doch
mal zu erübrigen, und einen Ansatz zu entwickeln. 

Ich selbst sehe mich zwar nicht als Anfänger, mein
jahrelanges _rekursives Gefühl_ sagt mir jedoch,
das es da grundsätzlich Schwierigkeiten gibt.  ???:L 



			
				SlaterB hat gesagt.:
			
		

> kann man ja grob an der Ausgangszahl abschätzen


Das halte ich für ein Gerücht.

Entweder geht es *exakt* oder eben gar nicht.


----------

