# Fakultäten berechnen.



## Thrawns (16. Mai 2009)

Hallo,
es ist zwar keine Hausaufgabe, sondern einfach eine Übung - aber das ist im Prinzip ja egal. 

*Aufgaben:*
1) Die Fakultät bis zu einer vom Benutzer eingegebenen Zahl berechnen lassen (Richtwert: bis 20).
2) Die Fakultät von 1000 berechnen lassen.

Ich würde mich aber erstmal gerne auf die erste Aufgabe konzentrieren. Die zweite bedarf wohl einiger Kniffe mit "BigInteger". Mir wäre es aber lieber, Aufgabe 1 erstmal auf einem leichteren Wege zu lösen. Als Grundlage.

Mir geht es dabei auch nicht um den kompletten Code, sondern einfach um die entscheidende Zeile der Fakultätsberechnung.

Hier erstmal was, ohne Benutzereingabe, sondern mit dem Ziel die Fakultät von 20 zu errechnen:

```
class Fakultaet
{
     static int i;
     static int x;
     static int ergebnis;
     
     public static void main (String[] args)
     {
          for (i=1; i<=20; i++)
          {
               XXXXXXXXXXXXXXXXXXXXXX
          }
     }

     System.out.println ("Die Fakultaet von 20 ist: " + ergebnis + ".");
}
```

Mir ist einfach nicht klar, wie ich es hinbekomme, dass wirklich alle ganze Zahlen vor 20 in der richtigen Reihenfolge multipliziert werden.


----------



## musiKk (16. Mai 2009)

Nun, da fehlt ja nicht viel. Ich weiß gar nicht, was man da sagen soll, ohne das komplette Ergebnis zu verraten. Darum nur was kleines: Du sprichst von "Reihenfolge". Die Fakultät wird auf die Multiplikation zurückgeführt, da spielt die Reihenfolge keine Rolle.


----------



## Schandro (16. Mai 2009)

innerhalb der Schleife ist i nacheinander 1, dann 2, dann 3 usw.. bis 20
Du brauchst nur eine Variable auf die nacheinander i dazumultipliziert wird.


----------



## Marco13 (16. Mai 2009)

Für 20 reicht int glaubich auch nicht, aber ein long dürft's tun. Für das zweite dann BigInteger, aber wenn du die erste erstmal hast, ist das nur umschreiben....


----------



## Thrawns (16. Mai 2009)

Danke für die Hinweise. Haben mir tatsächlich geholfen letztlich auf


```
class Fakultaet
{
     static int i;
     static int ergebnis = 1;
     
     public static void main (String[] args)
     {
          for (i=1; i<=10; i++)
          {
	      ergebnis = ergebnis*i;
          }
      
     System.out.println ("Die Fakultaet von 10 ist: " + ergebnis + ".");
     }
}
```

zu kommen. Bzw., nachdem ich es auf dem Papier ein paar Schritte durchgerechnet habe, ging's. 

Für 20 hat Int tatsächlich nicht gereicht. Deshalb habe ich erstmal 10 genommen.


----------



## Thrawns (16. Mai 2009)

Ok, ich habe jetzt noch folgendes gemacht:

1. alles ein wenig umstrukturiert: nicht mehr alles in einer "public static void main" Methode. Einfach, weil der Dozent ebenfalls diesen Programmierstil bevorzugt und es so ggf. einfach ist zu adaptieren.

2. programmiert, dass der User nun eingeben kann, von welcher Zahl er die Fakultät berechnen lassen möchte.

3. versucht das ganze wegen Punkt 2 (es soll ja weiter als bis 10, sondern auch bis 1000 gehen können) in einen BigInteger zu packen. Aber genau hier treten Probleme auf:
     a) ich habe das "import java.math.BigInteger" aus dem Skript übernommen. Muss ich vorher noch was besonderes dafür installieren? Wie sehe ich, ob der Import geklappt hat?
     b) habe ich Probleme mit der Multiplikation. Primitive Rechenzeichen funktionieren doch mit BigInteger nicht mehr!? Ist denn "variable.multiply" richtig?

Hier der aktuelle Code, darunter die Fehlermeldung:

```
import java.math.BigInteger;

class Fakultaet
{
	//Attribute
	int i;
	BigInteger ergebnis = new BigInteger("1");
     


	//Konstruktor	
	Fakultaet (int UserEingabe)
	{
		i = UserEingabe;
		rechnung();
	}



	//Methode
	void rechnung()
	{
		for (i=1; i<=10; i++)
          	{
	      		ergebnis = ergebnis.multiply(i);
		}
	System.out.println ("Ergebnis: " + ergebnis + ".");
        }



	//Main-Methode
	public static void main (String[]args)
	{
		Fakultaet NeuesObjekt=new Fakultaet (Integer.parseInt(args[0]));
	}

}
```


----------



## Schandro (16. Mai 2009)

> ich habe das "import java.math.BigInteger" aus dem Skript übernommen. Muss ich vorher noch was besonderes dafür installieren?


da java.math.BigInteger in der normalen Java API liegt, nein.



> Wie sehe ich, ob der Import geklappt hat?


Importe können nicht "klappen" oder "nicht klappen", importe sind nur Abkürzungen für schreibfaule Programmierer! Theoretisch könntest du absolut jeden Java Quellcode ohne einen einzigen import schreiben, wenn du immer:
java.util.*Vector*
javax.swing.*JButton*
java.math.*BigInteger*

statt

*Vector
JButton
BigInteger*

innerhalb des Quellcodes schreibst.




> Ist denn "variable.multiply" richtig?


ja.

Die Fehlermeldung kommt. weil die Methode "multiply", die auf einer Instanz von "BigInteger" aufgerufen wird, eine andere Instanz von "BigInteger" als Parameter erwartet. Du übergibst aber ein int.
=> du musst bei jedem Schleifendurchlauf einen BigInteger mit dem aktuellen Wert von "i" erstellen und diesen an "multiply" übergeben. Guck dir mal die API an, vorallem die Konstruktoren von "BigInteger".

€dit:
Du kannst aus einem int einen BigInteger z.b. hierdurch machen:
BigInteger myIntAsBigInteger = BigInteger.valueOf(i);
das ist übrigens kein Konstruktor, sondern eine Factory-Methode, nur so als Info^^


----------



## Thrawns (17. Mai 2009)

Danke für die Hilfe. Es scheint so zu klappen:


```
import java.math.BigInteger;

class Fakultaet
{
	int i;
	int x;
	String a;
	BigInteger ergebnis = new BigInteger("1");
	


	
	Fakultaet (int UserEingabe)
	{
		x = UserEingabe;
		rechnung();
	}




	void rechnung()
	{
		for (i=1; i<=x; i++)
          	{
			BigInteger a = BigInteger.valueOf(i);
	      		ergebnis = ergebnis.multiply(a);
		}
	System.out.println ("Ergebnis: " + ergebnis + ".");
        }



	
	public static void main (String[]args)
	{
		Fakultaet NeuesObjekt=new Fakultaet (Integer.parseInt(args[0]));
	}

}
```


----------



## Landei (18. Mai 2009)

Da du es hinbekommen hast, noch ein wenig Nörgelei:
- Variablen immer klein schreiben
- keine Instanzvariablen verwenden, wo lokale Variablen ausreichen
- dein Fakultät-Objekt kann nur einmal verwendet werden, dann braucht man ein neues. Das kann schnell ineffizient werden
- Eine Methode sollte *genau* eine Aufgabe erfüllen. rechne() erfüllt zwei Aufgaben (rechnen und ausgeben). Das ist zwar hier trivial, aber in großen Programmen wichtig (z.B. um Fehler besser finden zu können, Ergebnisse statt auf der Konsole in einem Fenster anzeigen zu lassen, Unit-Test leichter schreiben zu können usw.). Stichwort "Separation of Concerns"


```
import java.math.BigInteger;

public class Fakultaet {

    public BigInteger berechne(int n) {
         BigInteger ergebnis = BigInteger.ONE;
         for (i=1; i<=n; i++) {
             ergebnis = ergebnis.multiply(BigInteger.valueOf(i));
         }
         return ergebnis;
    }
	
   public static void main (String[]args) {
        Fakultaet fak=new Fakultaet();
        int x = Integer.parseInt(args[0]);
        System.out.printf("Ergebnis: %s.", fak.berechne(x).toString());
   }

}
```


----------

