Bitmanipulation ?

M

medi-tation

Gast
Hallo,

Zu einer kleinen Übungsaufgabe habe ich noch ein paar Fragen. Es sind verschiedene Themen eines Buches die ich mir mit kleinen Aufgaben etwas besser erklären will, und hierbei geht's um "Bit-Manipulation".

Im unteren Beispiel würde ich gern das erste Problem lösen, abseits von Bitmanipulation, weil das Programm nicht startet, zumindest kompiliert ?

Java:
import java.util.*;
import java.awt.*;

class KaffeMaschine {

 Timer t;
 
 public static void main(String[] args) {
  new KaffeMaschine().starten();
 }

 public void starten() {
  Calendar calendar = Calendar.getInstance();
  calendar.set(Calendar.HOUR_OF_DAY, 16);
  calendar.set(Calendar.MINUTE, 33);
  calendar.set(Calendar.SECOND, 0);
  Date time = calendar.getTime();
   
  t = new Timer();
  t.schedule(new Einschalten(), time);
 }
}


class Einschalten extends TimerTask {
 int eingabe;
 String geschmack;
 int dosis;
 boolean kaffe;
 boolean espresso;
 boolean kafferahm;

 Toolkit toolkit = Toolkit.getDefaultToolkit();

 public void aufwärmen() {
  try { 
   Thread.sleep(5000);
  } catch(InterruptedException e) {System.out.println("Sorry kann nicht starten");}
 } 

 public void run() {
  int eingabe = (int) (Math.random() * 3);
  switch(eingabe) {
   case 1: while(kaffe) {
            dosis = 3;
            geschmack = "leicht";
            System.out.println("Kaffee bereit!");
            toolkit.beep();
            break;
           }

   case 2: while(espresso) {
            dosis = 7;
            geschmack = "stark";
            System.out.println("Espresso bereit!");
            toolkit.beep();
            break;
           }

   case 3: while(kafferahm) {
            dosis = 4;
            geschmack = "mittel";
            System.out.println("Kafferahm bereit!");
            toolkit.beep();
            break;
           }
  }
 } 
}

Wenn es ausführbar ist, würde ich geren eine Frage zur Bitmanipulation stellen. Also, wie könnte man die Operatoren zur Bitmanipulation in den oberen Code setzen, damit zum Beispiel eine Kaffemaschine die nur seriell(bit) angesprochen werden kann, funktioniert.
Obwohl der Code einfach dargestellt ist, würde mich interessieren wie man so eine Bitmanipulation, für so eine serielle Kommunikation, darstellen könnte?

Vielen Dank
m
 
M

medi-tation

Gast
Kein Fehler wird angezeigt, man kompilierts und wenn man es ausführt bleibt es so, als wäre es in einer Endlosschleife ?
 

Jodo

Aktives Mitglied
Hast du mal ein paar
Code:
println()
's gesetzt um festzustellen wo er hängen bleibt?
Was mir auffällt: Du initialisiert die boolean Variablen in "Einschalten" nicht. Deine While-Schleifen brechen ohne bestimmte Bedingung ab, d.h. du brauchst da ja gar keine Schleife, wenn du sie sowieso mit einem break enden lässt.
 
M

medi-tation

Gast
Danke für die Antworten.

Ja das lag an der Schleife, hab es jetzt abgeändert, so weit funktionierts. Thanks

Aber jetzt habe ich noch die Frage, wegen der Bitmanipulation, wie könnte man den Code ändern das man die Kommunikation auf bit-Ebene aufnimmt, falls möglich mit diesem Code ?

Java:
import java.util.*;
import java.awt.*;

class KaffeMaschine {

 Timer t;
 
 public static void main(String[] args) {
  new KaffeMaschine().aufwärmen();
 }

 public void aufwärmen() {
  try { 
   Thread.sleep(5000);
  } catch(InterruptedException e) {System.out.println("Sorry kann nicht starten");}
  System.out.println("Maschine warm");
  starten(); 
 } 

 public void starten() {
  Calendar calendar = Calendar.getInstance();
  calendar.set(Calendar.HOUR_OF_DAY, 19);
  calendar.set(Calendar.MINUTE, 23);
  calendar.set(Calendar.SECOND, 0);
  Date time = calendar.getTime();
   
  t = new Timer();
  t.schedule(new Einschalten(), time);
 }
}


class Einschalten extends TimerTask {
 int eingabe;
 String geschmack;
 int dosis;
 boolean kaffe;
 boolean espresso;
 boolean kafferahm;

 Toolkit toolkit = Toolkit.getDefaultToolkit();
 
 public void run() {
  int eingabe = (int) (Math.random() * 3);
  switch(eingabe) {
   case 1: 
            dosis = 3;
            geschmack = "leicht";
            System.out.println("Kaffee bereit!");
            toolkit.beep();
            break;
 
   case 2: 
            dosis = 7;
            geschmack = "stark";
            System.out.println("Espresso bereit!");
            toolkit.beep();
            break;

   case 3: 
            dosis = 4;
            geschmack = "mittel";
            System.out.println("Kafferahm bereit!");
            toolkit.beep();
            break;
  } 
 }  
}

Danke
m.
 

r.w.

Bekanntes Mitglied
Ist Dir nebenbei bemerkt schon aufgefallen, dass
es bei Dir niemals Kaffeerahm gibt? ;-)

Dann versuch' mal mal so:
Java:
 int eingabe = (int) (Math.random() * 3) + 1 ;


Wenn Du mit "Kommunikation auf bit-Ebene" tatsächlich
die Kommunikation über eine serielle Schnittstelle meinst,
muss ich an der Stelle noch passen.

VG ROlf
 
M

medi-tation

Gast
Danke für den Hinweis, dieser Rahm, wie kann man den vergessen. :)

Ja womöglich RS-232, diese Schnittstelle wäre praktisch die geeignetste, kann man bis 120m verlegen.

Zum oberen Beispiel, dachte ich mir, man könnte mittels Operatoren(Bitmanipulation), dies so verändern das es zur Kommunikation passender wäre ?

Danke
m.
 

Kevin94

Top Contributor
Hast du wirklich vor mit Java eine real-existierende Kaffemaschine über den seriellen Port anzusteuern?
Wenn ja, respekt, du hast dir ein hohes Ziel gesteckt.
Hat die Maschiene schon ein Interface für eine externe Steuerung, oder musst du dir das noch zusammen löten?
Was die Bitperatoren angeht, würde ich mir darüber erst Gedanken machen, wenn weißt, wie du mit der Kaffemaschine kommunizieren kannst (und ob das überhaupt geht).
 
M

medi-tation

Gast
Nein ich möcht nicht eine real existierende Kaffemaschine steuern.
Es sollte, wie im ersten Post geschrieben nur als Lernhilfe dienen.

Im Buch "Java von Kopf bis Fuss", bin im Anhang-A die Themen am durcharbeiten, und nehme auch das Internet zur Hilfe, leider finde ich nicht immer, Verständliches.

Im Buch wird das Thema Bitmanipulation erklärt, aber nur kurz, es wurde auch erwähnt das man Bitmanipulation auch zum ansprechen eines Toasters benutzen könnte, der nur serielle Bitkommunikation versteht.
Desshalb meine Frage zur Kaffemaschine. Klar, der Code ist nicht auf irgendeine reale Maschine abgestimmt, dennoch sollte er aber, nur als Beispiel dienen.

Hier noch ein paar Fragen, zur Bitmanipulation.
Ich versuchte mit [c]getBytes()[/c] die bits auszugeben, was aber nicht so geht, gibts vielleicht eine andere Methode?
Wie ich gesehen habe kann man die bits einer variabel verschieben, wie könnte man die bits zum Beispiel zur Kommunikation(seriell ?) vorbereiten?

Danke
m.
 

Tecwan

Aktives Mitglied
Hm, ich habe vor Jahren mal an seriellen Schnittstellen herumgelötet, und damit diverse Relais ein- und ausgeschaltet,
und auch Messwerte auf mehreren Kanälen eingelesen.

Ich kann mich allerdings nicht erinnern, dabei jemals besonders tief in die Bitmanipulation eingestiegen zu sein.

Realisiert wurde das jedenfalls über die serielle Schnittstelle. Zwar werden da durch den Draht die Signale als Bits
aufgereiht versendet, aber ich denke nicht, dass du auf eine derart niedrige Ebene herabsteigen musst.
Das Signal wird übertragen, indem auf der Leitung in bestimmten Intervalen Spannung angelegt wird. Man presst
den Datenstrom "Spannung/keine Spannung" in ein Zeitraster und gibt alle paar Bits noch Kontroll-Bits dazu, um
sicherzugehen, dass das Zeitraster richtig empfangen wird (und die Übertragung stimmt). Außerdem ist es sinnvoll,
wenn Sender und Empfänger ein sogenanntes Handshaking vereinbaren, wenn also der Sender nur dann sendet,
wenn der Empfänger bereit ist, weitere Daten zu empfangen.
Aber all diese Dinge sind bereits in der Bezeichnung RS232 enthalten; sowohl die Spannungspegel als auch die
Übertragungsintervalle (zB. 9600 baud) und die Art ob mit oder ohne Handshaking, gerade/ungerade Parität, Anzahl
der Stopp-Bits etc.
Darum muss man sich eigentlich keine Gedanken machen. Die Weiterentwicklung nennt sich übrigens USB.

In der Praxis sieht es so aus, dass man eine Schnittstelle zum Lesen oder Schreiben geöffnet hat (unter Angabe
von Übertragungsrate, Parität, Stoppbitanzahl), und dann aus oder in einen Byte-Puffer gelesen/geschrieben hat.
Die Arbeit bestand hauptsächlich darin, eigene Protokolle für die Kommunikation zu entwickeln.
Aber die eigentliche Kommunikation erfolgte immer durch Übertragung ganzer Bytes.
Wenn beispielsweise 8 Relais an-, aus- oder umgeschaltet werden sollen, könnte jedes Bit des einen übertragenen
Bytes für je ein Relais stehen; die Zahl '255' schaltet alle Relais an/um/aus, '3' das erste und zweite.
Will man mehr, zB. ein Gerät zur Übertragung gesammelter Daten auffordern, wird das Protokoll etwas komplizierter.

Bei der Kaffemaschine dürfte es aber ähnlich simpel sein; es sind Knöpfe dran, die für "stark" (zB. Bit 0, 1, 2 gesetzt),
"mittel" (Bits 0, 1), "schwach" (nur Bit 0) stehen, dazu Bit 3 für Sahne.
Wer also starken Kaffee mit Sahne will, schickt eine 2^3+2^2+2^1+2^0=15.
 
M

medi-tation

Gast
@Tecwan

Danke für die Antwort auch den andern.

Da hast du gute Erfahrungen gemacht mit serieller Schnittstelle, interessant wie du das beschrieben hast. War sicherlich nicht leicht an der Schnittstelle herum zulöten.

Das mit dem senden von bytes und nicht bits, ist warscheinlich besser. Im Buch stand, dass der Toaster auf Grund starker Speichereinschränkungen nur auf "Bit-Ebene" gesteuert werden kann. Wahrscheinlich könnte man in so einer Situation die RS232-Schnittstelle mit entsprechendem Kabel, benutzen.

Bei deinem Beispiel, verstehe ich leider nicht ganz die Logik oder den Zusammenhang und das Resultat(15). Vielleicht auch weil ich nicht die bits(0-1) nicht sehe?

stark = 0-1-2 (bit) drei bits
mittel = 0-1 (bit) zwei bits
schwach = 0 (bit) ein bit
Sahne = 3 (bit) ein bit

Kaffe mit Sahne = 2^3 + 2^2 + 2^1 + 2^0 = 15.

Bei diesem Operator handelt es sich um den XODER(exklusives ODER), dass einen Wert zurück liefert wenn nur einer der enstsprechende Operanden(1,2,3,0) eingeschaltet sind.

Aber wie erkennst du in der Formel ob die bits eingeschaltet sind oder nicht, gibts vielleicht eine Methode um die bits anzuzeugen, falls nötig?

Vielen Dank
m.
 

Kevin94

Top Contributor
Tecan hat mit ^ nicht die "Java-Bedeutung" XOR gemeint sondern die allgemeine Bedeutung als Zeichen für eine Potenz.
Wenn du dich für die Binäre Repräsentation einer Zahl interresierst, hilft dir vll.
Code:
Integer.toBinaryString()
.

Wenn dir die Potenzschreibweise nicht gefällt, weil sie in Java nicht gebräuchlich ist, lässt sich das ganze auch mit dem Shift-Operator ausdrücken, dies ist aber ziemlich unübersichtlich/unverständlich:
Java:
int kaffeMitSahne=1<<3+1<<2+1<<1+1<<0;//==0x0F bzw. 15 oder 0b1111
 
M

medi-tation

Gast
Danke für den Hinweis auf die Methode, funktioniert.
Aber gibts so eine Methode nicht auch für "Strings" ?

Ok habe das mit der Potenz nicht beachtet, aber stimmt, wobei das Ergebnis nicht "14" sein müsste?

Wie hast du das mit den Shift-Operatoren gemacht, um zu wissen welche bits wo zu verschieben?

Vielen Dank
m.
 

Tecwan

Aktives Mitglied
Dualsystem-Crash-Beispiel

Ein Byte ist aus 8 Bits zusammengesetzt, wobei die einzelnen Bits von 0 bis 7 durchnumeriert werden.
Jedes Bit kann den Wert 1 oder 0 annehmen, wobei 1 für "Spannung" und 0 für "keine Spannung" stehen kann.

Code:
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
 0    0    0    0    1    1    1    1	an(1) oder aus(0)
                     8    4    2    1   2 hoch bitNr; Summe ist 15

0*128 + 0*64 + 0*32 + 0*16 + 1*8 + 1*4 + 1*2 + 1*1 = 15

Wenn man wissen, möchte, ob Sahne gewünscht ist, interessiert nur bit0.
Hat man eine Zahl z, erhält man den Zustand von bit0 logisch aus
Code:
  z  AND (2hoch0)
  z  AND 1
1111 AND 0001 = 0001

und für starken Kaffee die drei Bits bit3 bit2 bit1:
Code:
 z   AND (2hoch1 + 2hoch2 + 2hoch3)
 z   AND 14
1111 AND 1110 = 1110

Du kannst es dir dann so vorstellen, dass das (halbe) Byte an die Kaffemaschine vier Signale (4 Bit)
vermittelt, wobei das bit0 die Klappe für die Sahne öffnet, und die bits1-bit3 drei Klappen für
Kaffeepulver.
Will man schwachen Kaffee, werden eben weniger Klappen geöffnet:
Code:
 z   AND 14
0011 AND 1110 = 0010

Die AND-Verknüpfungen bestimmen aus der Gesamtinformation die interessierende Teilinformation. "AND 1" liefert den Sahne-Test, "AND 14" den Kaffe-Stärke-Test, wobei in unserem Fall das Ergebnis
Code:
0010 = 2 für schwachen
0110 = 4 + 2 = 6 für mittelstarken und
1110 = 8 + 4 + 2 = 14 für starken Kaffee steht.

(Man könnte das auch anders lösen, zB. dass AND 1000 für starken, AND 0100 für mittelstarken, und AND 0010 für schwachen Kaffe steht.)
 
M

medi-tation

Gast
Vielen Dank für die ausführliche Erklärung! Das mit dem binärsystem hilft um einiges. Jetzt muss ich dies nur noch mit den verschiedenen Operatoren umsetzen.

Noch eine Frage. Kann man die bits auch von einem String anzeigen? Intern wird, wenn ich mich nicht täusche, die Unicode-Tabelle angewandt.

Danke und gute Nacht
m.
 

Kevin94

Top Contributor
Ein String ist intern ein char-Array über das man iterieren kann (bzw. eine Kopie davon, siehe [c]String.getBytes()[/c] bzw.
Code:
String.toCharArray()
) und jedes einzelene Zeichen kann man sich genauso wie einen int auch mit Hilfe der schon genannten Methode in Binärschreibweise ausgeben lassen.
 

Tecwan

Aktives Mitglied
Kann man die bits auch von einem String anzeigen? Intern wird, wenn ich mich nicht täusche, die Unicode-Tabelle angewandt.

Mir ist nicht ganz klar, was du damit meinst.

Ein String wird durch ein Array vom Typ byte repräsentiert. Du kannst einen Text natürlich in seine
einzelnen Bytes zerlegen und diese dann in "Binärstrings" umwandeln.
(Die Codierung in Unicode hat damit erstmal nichts zu tun und ist ein anderes Thema. Unicode
Zeichen benötigen mehr Speicherplatz als nur ein Byte; in der Zeichenfolge eines Strings ist es
nicht so, dass jedes Zeichen nur ein Byte belegt; das gilt nur für Codierungen aus der Anfangszeit,
als Sonderzeichen und Umlaute noch nicht berücksichtigt wurden, zB. im ASCII.)

Den Text "starker Kaffee" in eine Bitfolge zu bringen, macht für die Kaffemaschine wohl wenig Sinn.
Ich nehme mal an, es geht dir eher um die Visualisierung eines Byte als Binärzahl:

Java:
String binaerString="";
Byte aByte=(byte)15;

for (int i=7; i>=0; i--) {
    binaerString+= ( (aByte & 1<<i)!=0 )? "1" : "0";
}
System.out.println(binaerString);


Code:
1<<i
bedeutet, dass ein "1" Bit i-mal nach links geschoben wird.
Beispiel:
Code:
00000001 << 3
wird zu
Code:
00001000  (= 8)
und ist das Gleiche wie 2 hoch 3.
Das wirkt etwas sperrig, ist aber für das Verständnis besser geeignet als zB.
Code:
Math.pow(2,3);

Das "Schieben" funktioniert auch mit anderen Bitmustern, zB. der Binärzahl 3:
Code:
00000011 << 3
wird zu
Code:
00011000 (=24)
Zu beachten ist dabei, dass das nicht das Gleiche ist wie 3 hoch 3 (=27), sondern
1 * 2 hoch 3 + 2 * 2 hoch 3, oder anders ausgedrückt:
bit0 (=1) um drei linksverschoben plus bit1 (=2) um drei linksverschoben.
 
M

medi-tation

Gast
Danke euch beiden.

Wollte nur wissen ob ein Zeichen(Buchstaben oder anderes) auch als binärmuster ausgegeben werden kann. Z.B. ist eine [c]3[/c] gleich [c]00000011[/c], aber was ist [c]hoch[/c] oder [c]?[/c]. Bei den Zahlen kann man dies berechnen mittels Bitmuster und Dualzahlen potenzieren, aber bei den Buchstaben und Zeichen dachte ich man müsste irgendwie auf die Unicode- oder ASCII-Tabelle benutzen ?
Wobei ich dies mit diesen Methoden die Kevin94 geschrieben hat, ausprobieren sollte, jedoch ein Array dazu erstellen müsste.

Was bedeutet das Fragezeichen und der Doppelpunkt [c]? "1" : "0";[/c] , vielleicht Lamdas, wo if und else anderst dargestellt werden ?

Vielen Dank
m.
 

njans

Top Contributor
Was bedeutet das Fragezeichen und der Doppelpunkt ? "1" : "0"; , vielleicht Lamdas, wo if und else anderst dargestellt werden ?

Das ist eine bedingte Zuweisung:
(Bedingung)?Wenn ja:Wenn nein;

du kannst natürlich das auch so schreiben:

Java:
if(bedingung)
{
  Wenn ja
}
else
{
  Wenn nein
}
 

Oben