Die Klassen Math und String

Aus ComeniusWiki

Eine der großen Stärken von Java sind vordefinierte Klassen, die in einer Bibliothek bzw. einem package mitgeliefert werden. Typische Beispiele für solche vordefinierten Klassen sind die Klassen Math und String, die beide im package java.lang enthalten sind.


Die Klasse Math

Die Sprache Java selbst sieht nur einfache arithmetische Operationen wie Addition, Subtraktion, Multiplikation etc. vor. Schon bei einfachen mathematischen Formeln müssen wir aber kompliziertere mathematische Funktionen verwenden wie z.B. Quadratwurzel, Sinus oder Cosinus. Die Designer von Java haben sich entschlossen, diese komplexeren mathematischen Funktionen in eine spezielle Klasse namens Math zu packen. Die Klassen von java.lang werden immer automatisch vom Java-Compiler verfügbar gemacht, so dass das package nicht importiert werden muss.

Dokumentation der Klasse java.lang.Math

Beispiele für die Verwendung von Methoden der Klasse Math:

Funktion Methode
Kreiszahl Pi Math.PI
Quadratwurzel von x Math.sqrt(x)
Potenz: x hoch a Math.pow(x,a)
Winkelfunktionen (sin, cos, tan) Math.sin(x)
Rundung Math.round(x)
Aufrunden Math.ceil(x)
Abrunden Math.floor(y)


Anwendungen

Die zwei Methoden enthalten jeweils Anwendungen aus der Klasse Math:


import java.util.Scanner;

public class Aufgaben{

Scanner eingabe;

public Aufgaben(){
   eingabe = new Scanner(System.in);
}

//Beispiel 1
public void wurzelBerechnen(){
   System.out.print ("Geben Sie eine Zahl ein: ");
   int x = eingabe.nextInt();
   if(x<0){System.out.println("Ungültige Eingabe!"); wurzelBerechnen();};
     //Durch den erneuten Aufruf der Methode wurzelBerechnen() erscheint sofort wieder die Eingabeaufforderung
   System.out.println("Die Wurzel von "+x+" ist "+Math.sqrt(x));
}


//Beispiel 2
public void gerundeteWurzel(){
   System.out.print ("Geben Sie eine Zahl ein: ");
   int x = eingabe.nextInt();
   if(x<0){System.out.println("Ungültige Eingabe!"); gerundeteWurzel();};
   System.out.println("Die gerundete Wurzel von "+x+" ist "+Math.round(Math.sqrt(x)));
}
}


Die folgenden Methoden können wieder in der Klasse Aufgaben implementiert werden und deren Scanner-Objekt nutzen. (Hinweis: In den Aufgaben werden Bedingungen wiederholt.)

Aufgabe 1

Erstelle eine Methode public void pythagoras(), die nach Eingabe der Seitenlänge der beiden Katheten eines rechtwinkligen Dreiecks die Länge der Hypotenuse berechnet. Bei Eingabe negativer Werte soll ein Hinweis ausgegeben werden.

<popup name="Lösungsvorschlag">

public void pythagoras(){
   
   System.out.print ("Geben Sie die Länge der ersten Seite ein: ");
   int a = eingabe.nextInt();
   System.out.print ("Geben Sie die Länge der zweiten Seite ein: ");
   int b = eingabe.nextInt();
   if(a<0|| b<0) {System.out.println("Negative Eingabe nicht möglich! "); pythagoras () ;}
   else {System.out.println("Die Länge der dritten Seite beträgt "+Math.sqrt(Math.pow(a,2)+Math.pow(b,2)));}
}

Im Rumpf der if-Anweisung ruft sich bei einer falschen Eingabe nach dem entsprechenden Hinweis die Methode selbst auf (pythagoras()). Das hat den Vorteil, dass nach dem Fehlerhinweis sofort wieder eine Eingabeaufforderung auf der Konsole angezeigt wird.
Man könnte das Ergebnis auch zuerst in eine Variable schreiben lassen und dann ausgeben. Dies empfiehlt sich bei komplexen Berechnungen:

double c = Math.sqrt(Math.pow(a,2)+Math.pow(b,2));
System.out.println("Die Länge der dritten Seite beträgt "+c);

Alternative Lösung (spezielle Methode aus dem Math-package):

public void pythagoras (){

System.out.print ("Geben Sie die Länge Kathete a ein: ");
double a=eingabe.nextDouble();
System.out.print ("Geben Sie die Länge Kathete b ein: ");
double b=eingabe.nextDouble();
if(a<0|| b<0) {System.out.println("Negative Eingabe nicht möglich! "); pythagoras () ;}
else{System.out.println("Die Länge der Hypothenuse des Dreiecks ist "+Math.hypot(a,b)+".");};}

</popup>


Aufgabe 2

Erstelle eine Methode public void kugel(), die nach Eingabe des Radius das Volumen und die Oberfläche der entsprechenden Kugel berechnet. (Achtung: Bei der Berechnung des Volumens lauert eine böse "Datentypfalle" !!)

<popup name="Lösungsvorschlag">

public void kugel(){
   
   System.out.print ("Geben Sie den Radius ein: ");
   double r=eingabe.nextDouble();
   System.out.println("Das Volumen der Kugel beträgt "+(double)4/3*Math.pow(r,3)*Math.PI);
   System.out.println("Der Flächeninhalt der Kugeloberfläche beträgt "+4*Math.pow(r,2)*Math.PI); 
}

Erläuterung: Wird bei der Berechnung von 4/3 keine Datentypumwandlung vorgenommen, wird das Ergebnis immer auf den int-Wert 1 abgerundet!! </popup>


Aufgabe 3

Erstelle eine Methode public void zylinder(), die nach Eingabe des Radius und der Höhe das Volumen und die Oberfläche des entsprechenden Zylinders berechnet.

<popup name="Lösungsvorschlag">

public void zylinder(){

System.out.print("Geben sie den Radius der Kreisfläche ein: ");
double r= eingabe.nextInt();
System.out.print("Geben sie die Höhe des Zylinders ein: ");
double h=eingabe.nextInt();
double v=Math.floor(Math.pow(r,2)*Math.PI*h);
double o=Math.floor(2*Math.pow(r,2)*Math.PI+2*r*Math.PI*h);
System.out.println("Die Oberfläche des Zylinders beträgt "+o+" Das Volumen beträgt "+v+"");
}

</popup>


Aufgabe 4

Erstelle eine Methode public void prismaberechnung(), die nach Eingabe der Seitenlänge des gleichseitigen Grundflächendreiecks und der Höhe des Prismas das Volumen und die Oberfläche berechnet.

<popup name="Lösungsvorschlag">

public void prismaberechnung(){

System.out.print("Geben Sie die Seitenlänge des Grundflächendreiecks ein: ");
double s = eingabe.nextInt();
System.out.print("Geben Sie die Höhe des Prismas ein: ");
double h=eingabe.nextInt();
double v=(s/2*Math.sqrt(3)*s)/2*h;
double o=(s/2*Math.sqrt(3)*s)/2+3*s*h;
System.out.println("Das Volumen des Prismas beträgt "+v+" und die Oberfläche "+o+"");

}

</popup>


Aufgabe 5

Schreibe eine Methode public void quadratzahlTest(), die überprüft, ob eine eingegebene Zahl eine Quadratzahl ist oder nicht. Das eigentliche Problem besteht darin, eine geeignete Bedingung zu formulieren.

<popup name="Lösungsvorschlag">

Grundidee: Wenn das Ergebnis der Wurzel gleich dem Ergebnis für den gerundeten Wurzelwert ist, dann handelt es sich um eine Quadratzahl. Denn nur in diesem Fall erhalten wir für die Wurzel eine ganze Zahl.

public void quadratzahlTest(){
   
   System.out.print ("Geben Sie die zu überprüfende Zahl ein: ");
   int x = eingabe.nextInt();
   if(Math.sqrt(x)==Math.floor(Math.sqrt(x))){System.out.println(x+" ist eine Quadratzahl.");}
   else{System.out.println(x+" ist keine Quadratzahl.");}
}

</popup>


Die Klasse String

Der Datentyp String ist in Java kein einfacher Datentyp wie etwa int oder double oder boolean, sondern eine Klasse. Eine Variable vom Typ String enthält daher nicht den String selbst, sondern sie enthält einen Verweis auf ein Objekt der Klasse String. Genau genommen ist ein String ein Array von Zeichen (Datentyp char). Folgende Darstellungsweisen drücken daher dasselbe aus:

String s = "Hallo";

char[] s = {'H', 'a', 'l', 'l', 'o'};

Eine wichtigsten Konsequenzen aus dieser Tatsache ist, dass Strings nicht mit dem Vergleichsoperator == verglichen werden können, denn der Vergleichsoperator prüft, ob die Verweise gleich sind und nicht, ob die Strings gleich sind, auf die verwiesen wird. Daher stellt die Klasse String eigens eine Methode equals() zu Verfügung, die diese Aufgabe erledigt. Daneben gibt es noch viele weitere interessante Methoden zum Umgang mit Zeichenketten, in denen der Array-Charakter von String-Objekten deutlich wird.


Dokumentation der Klasse java.lang.String


Aufgabe 1

Erstelle eine Klasse StringMethoden und kopiere folgenden Code in den Editor:

public class StringMethoden {

public void stringMethodenTesten(){

String s1 = "Nikolausi";
String s2 = "Mikolausi";
String s3 = "NIKOLAUSI";

//...
System.out.println("Methode 1: "+s1);
//...
System.out.println("Methode 2: "+s1.charAt(5));
//...
System.out.println("Methode 3: "+s1.endsWith("ausi"));
//...
System.out.println("Methode 4: "+s1.equals(s2));
//...
System.out.println("Methode 5: "+s1.equalsIgnoreCase(s3));
//...
System.out.println("Methode 6: "+s1.indexOf("i"));
//...
System.out.println("Methode 7: "+s1.indexOf("aus"));
//...
System.out.println("Methode 8: "+s1.length());
//...
System.out.println("Methode 9: "+s1.replace('l','m'));
//...
System.out.println("Methode 10: "+s1.startsWith("Niko"));
//...
System.out.println("Methode 11: "+s1.substring(4));
//
System.out.println("Methode 12: "+s1.substring(4,8));
//
System.out.println("Methode 13: "+s1.toLowerCase());
//
System.out.println("Methode 14: "+s1.toUpperCase());
}
}

Kompiliere das Programm und lasse die Ergebnisse auf der Konsole ausgeben. Ergänze nun das Programm mit einem Kommentar (// ...), der genau angibt, was jede dieser String-Methoden macht.

<popup name="Lösungsvorschlag">

public class StringMethoden {

public void stringMethodenTesten(){

String s1 = "Nikolausi";
String s2 = "Mikolausi";
String s3 = "NIKOLAUSI";

// Der folgende Methodenaufruf ...
//... gibt die Zeichenkette s1 auf der Konsole aus
     System.out.println("Methode 1: "+s1);
//... gibt den 6.Buchstaben der Zeichenkette s1 aus
     System.out.println("Methode 2: "+s1.charAt(5));
//... überprüft, ob die Zeichenkette s1 auf "ausi" endet.
     System.out.println("Methode 3: "+s1.endsWith("ausi"));
//... überprüft, ob s1 und s2 identisch sind
     System.out.println("Methode 4: "+s1.equals(s2));
//... überprüft, ob s1 und s3 ohne Berücksichtigung von Groß- und Kleinschreibung identisch sind
     System.out.println("Methode 5: "+s1.equalsIgnoreCase(s3));
//... gibt aus, an welcher Stelle der Buchstabe "i" in s1 erstmals vorkommt
     System.out.println("Methode 6: "+s1.indexOf("i"));
//... gibt an, an welcher Stelle der Teilstring "aus" in s1 erstmals vorkommt
     System.out.println("Methode 7: "+s1.indexOf("aus"));
//... gibt die Länge von s1 (= Anzahl der Zeichen) an
     System.out.println("Methode 8: "+s1.length());
//... ersetzt alle Vorkommnisse von "l" durch "m"
     System.out.println("Methode 9: "+s1.replace('l','m'));
//... überprüft, ob s1 mit dem Teilstring "Niko" beginnt
     System.out.println("Methode 10: "+s1.startsWith("Niko"));
//... gibt den Teilstring von s1 aus, der mit dem 5.Buchstaben beginnt
     System.out.println("Methode 11: "+s1.substring(4));
//... gibt den Teilstring von s1 aus, der mit dem 5. Buchstaben beginnt und mit dem 8. endet (Index[8], d.h. der 9. Buchstabe ist der erste, der nicht mehr enthalten ist)
     System.out.println("Methode 12: "+s1.substring(4,8));
//... gibt s1 in Kleinbuchstaben aus
     System.out.println("Methode 13: "+s1.toLowerCase());
//... gibt s1 in Großbuchstaben aus
     System.out.println("Methode 14: "+s1.toUpperCase());
}
}

</popup>


Aufgabe 2

Ergänze die Klasse StringMethoden um eine Methode, die für eine eingegebene Zeichenkette zählt und ausgibt, wie oft ein bestimmter Buchstabe vorkommt. Der Einfachheit halber soll die eingegebene Zeichenkette in Kleinbuchstaben umgewandelt werden. Hilfreich ist hier die Tatsache, dass eine for-Schleife auch mit Zeichen (z.B. 'a' bis 'z') funktioniert. Der Typ der Zählvariable ist natürlich dann char. Hinweis: Eine innere Schleife läuft jeweils durch die ganze Zeichenkette, um den gesuchten Buchstaben zu finden.

<popup name="Lösungsvorschlag">

public void buchstabenZaehlen(String txt){

//Zeichenkette in Kleinbuchstaben umwandeln
   txt=txt.toLowerCase();

//äußere Schleife läuft von a bis z
   for (char c = 'a'; c <= 'z'; c++){

      //Zählvariable, um festzuhalten wie oft der jeweilige Buchstabe auftritt
      int j=0;

      //innere Schleife läuft jeweils vom ersten bis zum letzten Buchstaben und zählt die Vorkommen des jeweiligen Buchstaben
      for(int i=0;i<=txt.length()-1;i++){
          if(c==txt.charAt(i)){j++;};}
      System.out.println("Der Buchstabe "+c+" kommt "+j+" mal vor.");
}
}

Das Programm kann zum Entschlüsseln von einfach verschlüsselten Texten (z.B. Caesarverschiebung) verwendet werden, indem man die Buchstabenhäufigkeit im verschlüsselten Text mit der Verteilung z.B. im Deutschen vergleicht. Je länger der Ausgangstext, desto höher die Trefferquote.

</popup>


Aufgabe 3

Carlchen Crypto ist sauer. Die NSA liest trotz seiner genialen Verschlüsselung immer noch seine mails. Nun hat er eine neue Idee: Er nimmt von einer Zeichenkette immer jeden zweiten Buchstaben und gibt ihn aus. Anschließend hängt er ausgehend vom zweiten Buchstaben wiederum jeden zweiten Buchstaben an. Beispiel: Aus "Deggendorf" wird (nach Umwandlung in Kleinbuchstaben) "dgedregnof". Erstelle eine Methode crypto2(), die nach Eingabe einer Zeichenkette Carlchens Idee umsetzt.

Zusatzaufgabe: Erstelle eine Methode crypto2Decode(), die nach eingabe eines mit crypto2() verschlüsselten Wortes dieses wieder dekodiert. Achtung: Es ist eine Fallunterscheidung hinsichtlich der Länge des Wortes (gerade oder ungerade) notwendig.

<popup name="Lösungsvorschlag">

public void crypto2(String txt){

//Umwandlung in Kleinbuchstaben
txt=txt.toLowerCase();

//Erster Teil der Zeichenkette: Ausgabe jedes zweiten Buchstaben ausgehend vom ersten Buchstaben
for(int i=0;i<txt.length();i+=2){
System.out.print(txt.charAt(i));}

//Zweiter Teil der Zeichenkette: Ausgabe jedes zweiten Buchstaben ausgehend vom zweiten Buchstaben
for(int i=1;i<txt.length();i+=2){
System.out.print(txt.charAt(i));}
}


Zusatzaufgabe

public void crypto2Decode(String txt){

//Überprüfen, ob Zeichenzahl gerade
if(txt.length()%2==0){
//In der Schleife wird abwechselnd ein Zeichen des vordere und des hinteren Teils (ab txt.length()/2) der Zeichenkette ausgegeben
for(int i=0; i<txt.length()/2;i++){
System.out.print(txt.charAt(i));System.out.print(txt.charAt(txt.length()/2+i));}
}

//Zeichenzahl ungerade
else{
//In der Schleife für die ungerade Länge müssen die die Schleifenbedingungen angepasst werden
for(int i=0; i<=txt.length()/2;i++){
System.out.print(txt.charAt(i));if(txt.length()/2+1+i<txt.length()){System.out.print(txt.charAt(txt.length()/2+1+i));};}
}
}

Die if-Bedingung im Schleifenrumpf bei den ungeraden Zeichenketten vermeidet eine outOfBounds-Exception, indem der Versuch vermieden wird, ein Zeichen auszugeben, das sich außerhalb der Länge der Zeichenkette befindet.

</popup>


Aufgabe 4

Das bekannte Wortspiel bzw. Lied "Drei Chinesen mit dem Kontrabass" soll als Methode dreiChinesen() umgesetzt werden, wobei der gewünschte Vokal den Eingabewert darstellt.

<popup name="Lösungsvorschlag">

public void dreiChinesen(char voc){

String txt="Drei Chinesen mit dem Kontrabass";

for(int i=0;i<txt.length();i++){
//Ermitteln der Vokale in der Zeichenkette
if(txt.charAt(i)=='a'||txt.charAt(i)=='e'||txt.charAt(i)=='i'||txt.charAt(i)=='o'||txt.charAt(i)=='u'){
//Ersetzen des Vokals durch den eingegebenen Vokal
 System.out.print(voc);}else
//Ausgabe der anderen Zeichen ohne Veränderung
{System.out.print(txt.charAt(i));};
}
}

</popup>


Aufgabe 5

Carlchen hat jetzt endgültig die Nase voll von den Schnüfflern der NSA. Er wandelt nun seine Texte in eine Kette von Binärzahlen ohne Punkt und Komma um. Daran soll sich die NSA die Zähne ausbeißen. Erstelle eine Methode crypto3(), die mit Hilfe der Methode Integer.toBinaryString(int i) (Hinweis: Auch char wird hier wie int behandelt.) ein Zeichen nach dem anderen in eine Binärzahl umwandelt und ausgibt, so dass am Ende eine lange Kette von Nullen und Einsen dasteht. Um Problemen aus dem Weg zu gehen, sollte die Zeichenkette txt in Kleinbuchstaben umgewandelt werden und anschließend sollten alle Leerzeichen mit txt.replaceAll(" ","") entfernt werden.

Zusatzaufgabe 1: (Knobelaufgabe!): Carlchen will das Ganze natürlich auch wieder dekodieren. Erstelle eine Methode crypto3Decode(), die das bewerkstelligt. Dazu muss man drei Dinge wissen: 1. Jedes Zeichen bzw. jede ASCII-Zahl, die ein Zeichen 'a' bis 'z' bzw. 'A' bis 'Z' ausgibt, kann durch eine 7-stellige Binärzahl dargestellt werden (dezimal 65 bis 122), die wir mit einer der bekannten String-Methoden aus der langen Kette herausschneiden können. 2. Mit Integer.parseInt(String c, 2) können wir einen Binärzahl-String c in eine Dezimalzahl umwandeln. 3. Mit (char) x können wir eine Zahl x (Datentyp int) in ein Zeichen umwandeln. Besondere Vorsicht ist geboten mit dem Datentyp der Variablen, in denen die Zwischenergebnisse der Umwandlung abgespeichert werden.

<popup name="Lösungshinweise für die Zusatzaufgabe">

public void crypto3Decode(String txt){

//Schleife durchläuft in 7er-Schritten den Binärzahl-String (Beginn des nächsten Zeichens)
  

//Erfassen des 7-stelligen Binärzahl-Strings mit einer geeigneten Methode der Klasse String
  

//Umwandeln des Binärzahl-Strings in eine Dezimalzahl
  

//Umwandeln der (ASCII)-Zahl in das entsprechende Zeichen
  

//Ausgabe des Zeichens
  

}

</popup>


<popup name="Lösungsvorschlag">

public void crypto3(String txt){

//In Kleinbuchstaben umwandeln
  txt=txt.toLowerCase();

//Leerzeichen entfernen
  txt=txt.replaceAll(" ","");

//Schleife durch die Zeichenkette durchlaufen lassen
  for(int i=0;i<txt.length();i++){

//Das jeweilge Zeichen in einen Binärzahl-String umwandeln

  String b=Integer.toBinaryString(txt.charAt(i)); 

//String ausgeben
  System.out.print(b);}
}


//Binärzahl-String mit Anführungszeichen (!) eingeben 
  public void crypto3Decode(String txt){

//Schleife durchläuft in 7er-Schritten den Binärzahl-String
  for(int i=0;i<txt.length();i+=7){

//Erfassen des 7-stelligen Binärzahl-Strings
  String c=txt.substring(i,i+7); 

//Umwandeln des Binärzahl-Strings in eine Dezimalzahl
  int d=Integer.parseInt(c, 2); 

//Umwandeln der (ASCII)-Zahl in das entsprechende Zeichen
  char e=(char) d; 

//Ausgabe des Zeichens
  System.out.print(e);
}
}

</popup>


Aufgabe 6

Erstelle eine Methode woerterZaehlen(), die nach Eingabe eines Satzes ausgibt, aus wievielen Wörtern der Satz besteht.

<popup name="Lösungsvorschlag">

 public void woerterZaehlen(String txt){

//Zählvariable um die Zahl der Wörter abzuspeichern. Initialisierung mit Wert 1, da die Zahl der Wörter gleich Zahl der Leerstellen + 1
  int j=1;

//Schleife läft durch die ganze Zeichenkette
  for(int i=0; i<txt.length();i++){

//Die Zählvariable j wird um 1 erhöht, wenn ein Leerzeichen als Wortgrenze gefunden wird
  if(txt.charAt(i)==' '){j++;}
  }

//Endwert von j ausgeben
  System.out.println("Der Satz hat "+j+" Wörter.");
  }

</popup>