Erste Schritte Hausaufgabe: Addieren im Zweierkomplement

rayan_ben

Mitglied
Ganz grob: Es wird Zahl mit einem int-Parameter aufgerufen. Es wird dann ein das boolean-Array zweierKomplement erzeugt. Wir sollen den Konstruktor und die Addiere-Methode schreiben. Im Code unten ist die Methode 'private boolean[] dualZahl(long positiveZahl)' schon vorgegeben, die sollen wir im Konstruktor auch benutzen.

Meine Fragen:
Warum der ganze Umstand mit dem boolean-Array in der Aufgabe, warum keine Einsen und Nullen? Nur zur allgemeinen Verwirrung? Die Methode dualZahl funktioniert ja nur bei positiven Zahlen. Für negative muss ich ja erstmal invertieren und plus eins rechnen. Dafür muss ich aus true und false ja erstmal wieder 1 und 0 machen (oder etwa nicht) und wenn ja, wo mache ich das am besten? Ich gehe davon aus, dass ich nur dort wo IHR CODE steht, auch Code schreiben soll.

Ich fange mal an:
if (wert größer gleich 0)
{einfach methode dualZahl aufrufen}
else{nun geht der spaß ja schon los. soll ich jetzt im konstruktor eine methode schreiben, die die einsen und nullen invertiert zuweist, dann auf die addiere-methode zugreift (die noch nicht geschrieben ist)?}




Die Aufgabe:
Code:
public class Zahl {
  
  /* Attribute */
  
  private boolean[] zweierKomplement;
  
  
  /* oeffentliche Methoden */
  
  // Konstruktor
  public Zahl(int wert) {        
    
    [COLOR="Red"]/* IHR CODE */[/COLOR]
    
    
  }  
  
  
  
  // Getter
  public boolean[] getZweierKomplement() {
    return zweierKomplement;
  }
  
  // gibt zweierKomplement mit Einsen und Nullen als String zurueck
  public String toString() {
    String str = "";
    for (int i=31; i>=0; i--)
    if (zweierKomplement[i])
    str += "1 ";
    else
    str += "0 ";
    return str;
  }
  
  // addiert die Zahl andere zum Attribut zweierKomplement des Objekts, 
  // die resultierende Zahl wird in zweierKomplement gespeichert
  public void addiere(Zahl andere) {
    
    [COLOR="red"]/* IHR CODE */[/COLOR]
     
           
  }
  
  // berechnet fuer eine positive Zahl die entsprechende Dualzahl in 32 Bit
  // der Parameter ist vom Typ long, damit auch 2^31 uebergeben werden kann, 
  // was keine int-Zahl ist
  // Annahme: Parameter positiveZahl ist nichtnegativ.
  private boolean[] dualZahl(long positiveZahl) {
    // Array dual wird erzeugt und damit seine Elemente mit false 
    // initialisiert (Default-Wert von Boolean); 
    // (generell sollte man aber explizit initialisieren!)
    boolean[] dual = new boolean[32]; // Typ int hat 32 Bit
    
    int index = 0; // gibt die Stelle im Array an, die berechnet wird
    // laufe durch alle Stellen gemaess der bekannten Umrechnung von 
    // Dezimalzahl in Basis 2
    while (positiveZahl > 0){
      // aktuelle Stelle im Dualsystem durch Modulo 2
      if (positiveZahl % 2 == 1) {
        dual[index] = true;
      }
      else {
        dual[index] = false;
      }
      // neuen Wert durch Division mit 2
      positiveZahl /= 2;
      index++;
    }
    return dual;
  }
  
}
Code:
public class TestZahl {
    public static void main(String[] argumente) {
        // Erzeuge Objekte der Klasse Zahl
        // gebe die jeweiligen 2er Komplement-Darstellungen aus
        // Verwende einige  Male beispielhaft die addiere-Methode
        
        Zahl z1 = new Zahl(-256);
        Zahl z2 = new Zahl(512);
        System.out.println("z1: " + z1); // verwendet z1.toString()
        System.out.println("z2: " + z2);
        System.out.println("Addiere z1 zu z2");
        z2.addiere(z1);
        System.out.println("z2: " + z2);
        System.out.println();
        
        Zahl z3 = new Zahl((int) (-Math.pow(2,31)));
        System.out.println("z3: " + z3);
        System.out.println("Addiere -1 zu z3");
        z3.addiere(new Zahl(-1));
        System.out.println("z3: " + z3);
        System.out.println();
        
    
        Zahl z4 = new Zahl((int) (Math.pow(2,31)-1));
        System.out.println("z4: " + z4);
        System.out.println("Addiere 1 zu z4");
        z4.addiere(new Zahl(1));
        System.out.println("z4: " + z4);
    }
}

Ausgabe soll etwa so sein:
Code:
z1: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0
z2: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
Addiere z1 zu z2
z2: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
z3: 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Addiere -1 zu z3
Warnung: Unterlauf
z3: 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
z4: 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Addiere 1 zu z4
Warnung: Ueberlauf
z4: 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 
S

Spacerat

Gast
Du könntest die beiden Arrays entweder per Verknüpfung oder iterativ mit Overflow- (bzw. Carry-) Flag addieren. Das hat aber irgendwie nicht mehr viel mit dem eigentlichen Verständnis des Zweierkomplements zu tun (da würde ich mir an deiner Stelle auch keinen Kopf mehr machen) sondern mehr mit Rechnen im Binärsystem.
Im Konstruktor würde ich deswegen die übergebenen Werte stets in ein boolean-Array der gesamten Range (in diesem Fall 32) packen (ganz normal, wie sie ist und nicht invertiert), damit man anschliessend bei "addiere" halt auf diese Range nicht mehr achten muss.
 
Zuletzt bearbeitet von einem Moderator:

rayan_ben

Mitglied
Ja wie? Ich versteh's nicht.

Das schreibe ich in den Konstruktor:
Code:
zweierKomplement = dualZahl(wert);

Dann funktioniert
Code:
Zahl z2 = new Zahl(512);
wunderbar, weil es eine pos. Zahl ist.

Code:
Zahl z1 = new Zahl(-256);
würde aber doch nur Unsinn ergeben.

Das ist die Aufgabe zum Konstruktor:
Konstruktor: Die Klasse hat einen Konstruktor, welcher einen int-Parameter übergeben bekommt.
Für diesen Parameter soll das entsprechende 32-Bit Zweierkomplement berechnet und im Attribut
zweierKomplement gespeichert werden. Das Attribut zweierKomplement ist vom Typ boolean-Array
und soll für jede 0 ein false und für jede 1 ein true enthalten. Steht in einer Testklasse z.B. der Ausdruck new Zahl(-2), soll der Konstruktor von Zahl das Attribut zweierKomplement von dem neuen
Objekt auf einen neu erzeugten 32-elementigen boolean-Array setzen, bei dem das Element mit Index 0
false ist und alle anderen Elemente true sind entsprechend der 32-Bit Zweierkomplement-Darstellung
11111111111111111111111111111110 von -2. Das bedeutet, dass das Vorzeichen-Bit im Element mit
Index 31 steht.

Aber schön, dass hier auch mitten in der Nach jmd. antwortet. Ich hau mich gleich hin. Abgabe ist morgen 12h, vielleicht schau ich kurz vorher nochmal drüber. Ich hab mir die Aufgabe jetzt bestimmt 4 Stunden angeguckt, viel mehr als die Zeile ist mir nicht eingefallen, weil ich nicht weiß, was ich mit einer negativen Zahl als erstes machen soll (generell schon: invertieren und +1 um in die 2-K-Darstellung zu kommen).

Methode addiere: Die Methode addiere soll folgendermaßen implementiert werden: Sie bekommt einen
Parameter Zahl andere, also ein anderes Zahl-Objekt übergeben. Es soll eine Addition unter Verwendung der Attribute zweierKomplement des aktuellen Objektes (this) und des Objektes anderes
ausgeführt werden und das Ergebnis wieder im Attribut zweierKomplement vom aktuellen Objekt gespeichert werden. Es soll ein Checkbit verwendet und eine Warnung auf der Konsole ausgegeben werden,
falls ein Unter- oder Überlauf stattgefunden hat.
Ich soll also wirklich mit true und false addieren?

für den ersten index wäre das: false + false = false oder false + true = true oder true + true = false + 1 übertrag oder wie?
 
Zuletzt bearbeitet:
S

Spacerat

Gast
Code:
Zahl z1 = new Zahl(-256);
würde aber doch nur Unsinn ergeben.
So wie mir nicht aufgefallen ist, dass es bereits eine Methode zum Erstellen des Arrays gibt, ist dir wohl entgangen, dass diese Longs aufnehmen kann. Da kann man doch das int entsprechend Wandeln: [c]long unsignedInt = inVal & 0xFFFFFFFFL;[/c]
Ich soll also wirklich mit true und false addieren?

für den ersten index wäre das: false + false = false oder false + true = true oder true + true = false + 1 übertrag oder wie?
Genau so... gibt's ein Problem damit?
 

rayan_ben

Mitglied
So wie mir nicht aufgefallen ist, dass es bereits eine Methode zum Erstellen des Arrays gibt, ist dir wohl entgangen, dass diese Longs aufnehmen kann. Da kann man doch das int entsprechend Wandeln: [c]long unsignedInt = inVal & 0xFFFFFFFFL;[/c]
Daas sagt mir gar nix, das habe ixh noch nie gesehen. du musst bedenken, dass wir seit 11 Wochen Java haben. Ich kann nicht viel: if, while, Arrays, Attribute, Vererbung...


Genau so... gibt's ein Problem damit?
nö, ich bin mir nur immer nicht sicher, ob das so der gedachte weg ist.
 
S

Spacerat

Gast
11 Wochen Java und noch nicht eine UND-Verknüpfung angewendet? :shock:
Was soll's, wenn man an eine Methode die longs erwartet ints übergibt, werden diese ints nicht einfach bitweise übergeben, sondern vorher inkl. N-Flag-Extension in ein long gewandelt. Daraus folgt, negative ints werden entsprechend negative longs und selbiges gilt analog für positive ints (negative ints werden mit 1-Bits und positive mit 0-Bits aufgefüllt). Durch diese UND-Verknüpfung mit den unteren 32 Bits eines longs gesetzt (0xFFFFFFFFL) isoliert man den int-Anteil des Wertes bereits vor den JVM-Internas und verhindert damit die sonst folgende N-Flag-Extension.
 

Basti46

Mitglied
Oh man ich sitze auch gerade an dieser Hausaufgabe. Mit
Java:
 long unsignedInt = inVal & 0xFFFFFFFFL;
kann ich leider auch nichts anfangen. Hat vielleicht noch jemand einen anderen Tipp wie man an die Aufgabe rangeht? Ich sitze echt auf dem Schlauch.
 
S

Spacerat

Gast
...liegt es evtl. daran, dass ich ein "t" bei "intVal" (Integerwert) vergessen habe?
Ist doch im Prinzip recht einfach:
Das Zweierkomplement besagt, dass das MSB als Negativ-Flag interpretiert wird. Erweitert man die Bitfolge von 32 auf 64 Bit, so müssen bei negativen Werten alle Bits von 32 bis 63 mit 1 gefüllt werden, damit am Ende wieder der Wert stimmt. Das macht die JVM für uns bei einem einfachen Cast. In der Aufgabe aber soll diese die N-Flag-Extension aber verhindert werden und das erreicht man mit dieser UND-Verknüpfung (isoliert die Bits 0 bis 31 und castet auf positiv long).
Wenn ich's aber recht überlege, kann man sich das auch sparen, weil in der Methode "dualZahl()" ohnehin nur die untersten 32 Bit berücksichtigt werden. "-256" würde also auch korrekt funktionieren.
 
Hey Leute, ich bin auch endlich bei dieser Aufgabe angekommen =D.
Meine Frage wäre, wie man hier eine Dualzahl, welche boolisch ist, in Zweierkomplement darstellen kann. Einerkomplement würde mit ~ invertiert werden. Aber 1 addieren? Zu invertierter Dualzahl (boolisch) wie? Einfach mit true ? Ich wäre für eure Hilfe sehr dankbar .
 

Neue Themen


Oben