Zum Inhalt springen

Empfohlene Beiträge

Geschrieben

Hallo!

Ich habe folgendes Problem:

Ich kann zwar den Binärwert einer Dezimalzahl schön und richtig (durch Bitshifting) am Bildschirm ausgeben:

int value = 103179880;

int i = 0;

int int_bit_size = 32;

for(i = 0; i < int_bit_size; i++){

printf("%d", (value & 0x80000000) >> 31);

value <<= 1; }

aber wie kann ich diesen Binärwert in einer Variable speichern??

Lg Stefan

Geschrieben
Daten werden immer Binär gespeichert, alles andere ist nur Darstellungssache

Offensichtlich soll die Binärdarstellung gespeichert werden. :D

Das einfachste wäre wohl, sprintf zu benutzen, und alle Einzelergebnisse zusammenzuhängen (strcat).

Geschrieben

Hmm, ich versteh das Problem nicht so recht.

Du hast doch bereits 32 bits in einem signed int gespeichert?

Meinst Du zum Zwischenspeichern einzelner Bits? Es gibt bool, aber

auf einem 16bit System oder höher ist das ohnehin Verschwendung und nur der besseren Lesbarkeit her ok.

In C++ gibt zum Beispiel auch bitset.

Geschrieben

Ich will eine Gleitkommazahl (Typ float) in einen ASCII String konvertieren!

Dazu brauche ich den Wert der Mantisse (und der ist in Binärform)!

Ich will das komplette Binärmuster speichern zB (10001101..)

Problem:

for(i = 0; i < int_bit_size; i++){

printf("%d", (value & 0x80000000) >> 31);

value <<= 1; }

Wenn ich anschließend value ausgeben will bleibt nur der wert des letzten bits erhalten (also 0 oder 1) brauche aber das ganze Bitmuster!!!

printf("%d\n",value); --> = 0 oder 1

Geschrieben
Dazu brauche ich den Wert der Mantisse (und der ist in Binärform)!
Alles, was im Computerspeicher liegt, ist in Binärform, weil der Computer nichts anderes beherrscht.

Ich will das komplette Binärmuster speichern zB (10001101..)
Ist dir klar, dass der Wert derselbe ist, egal welche Darstellung du benutzt?

Wenn ich anschließend value ausgeben will bleibt nur der wert des letzten bits erhalten (also 0 oder 1) brauche aber das ganze Bitmuster!!!
Das liegt daran, dass value während der Berechnung zerlegt wird. Das "Bitmuster" war vorher in value. Wenn du das später nochmal anzeigen musst, dann kopier den Wert doch einfach vorher in eine andere Variable.

das heißt ich habe das Bitmuster am Bildschirm zwar ausgegeben, aber ich kann damit nicht weiter rechnen!!
Die Binärdarstellung ist ein Text, mit dem kannst du sowieso nicht rechnen.
Geschrieben

Meine ich das nur, oder wird die Variable in der Schleife da jedesmal überschrieben? (ist schon eine ganze Weile her, dass ich das letzte mal was mit C zu tun hatte :rolleyes: ) Dann könnte die am Ende ja nicht den kompletten Wert enthalten, sondern nur den Endwert nach Durchlaufen der Schleife. :rolleyes:

Geschrieben

Naja die Aufgabenstellung ist auf jeden Fall folgende:

Die Konvertierung einer Gleitkommazahl zu einem ASCII-String kann mit

Hilfe des folgenden Algorithmus berechnet werden:

1. Berechne Mantisse und Exponent der Gleitkommazahl wie im vorherigen

Beispiel beschrieben. --> Alles klar

2. Denormalisiere die Zahl, sodass der Exponent 0 ist. Dies erreicht

man durch Shiften der Binärzahl. --> auch klar

3. Konvertiere die binäre Zahl vor dem Komma in die dezimale Darstellungsform.

Dies kann man durch Addition aller Binärwerte, die mit ihrem Stellenwert 2i multipliziert werden, erreichen, wobei k das höchstwertige Bit (MSB) ist. Danach erhält man den entsprechenden ASCII-Wert durch die Addition mit dem ASCIIWert

der Ziffer '0'.

--> daher brauche ich die Binärwerte zum weiterrechnen! (jeweiliges Bit * 2 ^exponent)

4. Konvertiere nun auch die binäre Zahl nach dem Komma in die dezimale

Darstellungsform. Diese Zahl kann wie folgt berechnet werden:

wobei j das niederwertigste Bit (Least Signicant Bit - LSB) darstellt.

Geschrieben
Meine ich das nur, oder wird die Variable in der Schleife da jedesmal überschrieben?

Nein, wird nicht direkt überschrieben, denn in:

printf("%d", (value & 0x80000000) >> 31);

ist der Bereich um value nur ein rvalue, also nix geschrieben

und in:

value <<= 1; // value = value << 1

bit shift links um 1 bit und rechts mit 0 auffüllen.

das bedeutet, dass in jedem Schleifendurchlauf an der 32.Stelle (MSB) das printf() kommt.

Geschrieben

das heißt im endeffekt ist nur mehr das MSB in der variable und alle anderen sind 0!

gibt es eine Möglichkeit vor jedem bitshift zB mit strcat oder sprintf die bits in eine (andere) variable einzulesen??

Geschrieben

gibt es eine Möglichkeit vor jedem bitshift zB mit strcat oder sprintf die bits in eine (andere) variable einzulesen??

Ja, indem du die Funktion einfach vor dem Shift aufrufst. :rolleyes:

Geschrieben

Mal ganz davon abgesehen, kann ich immer noch nicht ganz das Problem mit dem Code inbezug auf die Aufgabenstellung begreifen.

Du willst den Vorkommateil eines float, den Du bereits als int hast durch Summieren der bit-Wertigkeiten in Dezimaldarstellung haben und als zweiten Schritt durch Addieren des ASCII-Wertes der '0' als ASCII darstellen?

int i, dezimal = 0, mask = 1;

    for ( i = 0; i < 32; ++i )

    {

        dezimal += (value & mask) ? mask : 0;

        printf("%d & %x = %d => %d \n", value, mask, value&mask, dezimal); //debug

        mask <<= 1;

    }

Damit summierst Du die binärwerte; Wieviele Stellen kann ein int als Text maximal haben? 10+1Vorzeichen also passt char[12]
while ( dezimal )

    {

        char c = '0' + dezimal % 10;

        // mit strcat in textpuffer schreiben

        dezimal /= 10;

    }

Geschrieben

konkret ist die Aufgabenstellung so:

Umwandlung einer 32Bit-Gleitkommazahl (also float) in einen String (ASCII-Zeichen).

Es müssen mind. 4 Vorkomma- und 4 Nachkommastellen umgewandelt werden unter Verwendung simpler Bitoperationen wie shift, and, or, subtract.

Die C-Version soll dann als Vorlage für denselben Vorgang in Assembler dienen..

Geschrieben

falls das was hilft: So wäre die Lösung für einen Integer-Wert,

ich suche die Lösung für einen float-Wert!

void RNOInteger::toASCII_c(char str[])

{

int int32=value;

char c;

int i = 0;

do {

str[i++]=int32 % 10 + '0';

int32 /= 10;

} while (int32 > 0);

str[i--] = '\0';

// reverse order

for (int x = 0, y = i; x<y; x++, y--) {

c = str[x];

str[x] = str[y];

str[y] = c;

}

}

Das ist die header-Datei dazu:

#ifndef RNOINTEGER_H_

#define RNOINTEGER_H_

#include <iostream>

using std::ostream;

typedef unsigned int UInt32;

class RNOInteger

{

private:

UInt32 value;

public:

RNOInteger(void); // default constructor

RNOInteger(UInt32 val); // constructor to initialize instance with 32-bit integer

~RNOInteger(void); // destructor

void toASCII_c(char str[]); // conversion into ASCII in C

void toASCII_asm(char str[]); // conversion into ASCII in Assembler

friend ostream& operator << (ostream&, const RNOInteger&);

};

// Input- and output operators

ostream& operator << (ostream& outstr, const RNOInteger& RNOInt);

#endif /* RNOINTEGER_H_ */

Geschrieben

hmm, die Lösung für den int schaut ziemlich so aus, wie mein Vorschlag, ich hab aber tatsächlich, das reverse vergessen.

Fakt ist ein float (single nach IEEE 754, Link zu wiki wurde bereits hier gepostet) besteht aus 23 bit Mantisse vom LSB ab, dann 8 bit Exponent und 1 bit Vorzeichen (MSB).

Jetzt musst du nur noch aus dem float zwei int's machen (ein Vorkomma-Int und ein Nachkomma-Int) und die umwandeln.

In der Aufgabenstellung steht sogar schon was wegen denormalisieren, ...

Geschrieben

Hallo,

das ist ein interessantes Thema.

Mit

float f=3.1415926f;

kann ich eine Zahl abspeichern und mit

adr=&f;

die Adresse der Zahl abfragen.

Aber wie bekomme ich daraus die vier Byte, in denen die Zahl dargestellt wird?

Mit (char)*adr geht das nicht- Ergebnis=0.

Ich glaube, mal gelesen zu haben, es ginge mit "bitfields".

Aber ich weiß nicht mehr genau.

Ich musste mal ein Programm schreiben, das aus einer Folge von 0 und 1 die dazugehörige Dizimalzahl berechnet. Aber wie bekomme ich eine float-Zahl dazu, mir ihre vier Byte zu übergeben?

LG

André

Geschrieben

Hallo,

Aber wie bekomme ich eine float-Zahl dazu, mir ihre vier Byte zu übergeben?

naja, float ist genauso groß wie ein int (auf 32 bit systemen). Deshalb kannst du einen erzwungenen typecast machen, direkt den speicher kopieren oder gleich mit nem union zugreifen.

Aber aus den 4 bytes wird dann trotzdem nur über Bitpobelei irgendetwas anderes wie eine Dezimalzahl :D

Geschrieben

Danke für die Hilfe! Bin jetzt schon gut im Rennen ;)

Was geht:

Habe den float in 2 int's eingelesen (ganzzahl und rest)

Vorzeichen berechnen

Exponenten berechnen

binäre (reduzierte & erweiterte) mantisse ausgeben

normierte mantisse/denormalisierte mantisse in dezimal und binärwerten ausgeben

Das einzige Problem noch: ich bekomm als ascii-code bei ganzzahl 2345 und bei rest 1 raus, das kann nicht ganz richtig sein??

void RNOFloat::toASCII_c(char str[])

{

// add your c code of the algorithm here

float RNOFloat = value; //Gleitkommazahl, die konvertiert werden soll

unsigned int *ptr, bit, maske;

int i, exp, vorzeichen;

int ganzzahl = abs( static_cast<int>(RNOFloat) );

printf("\nGanzzahl: %d",ganzzahl);

printf("\n");

int rest = abs ( static_cast<int>((RNOFloat - ganzzahl) * 100000));

printf("Rest: %d",rest);

printf("\n\n");

ptr = (unsigned int*) &RNOFloat;

bit = *ptr;

maske = 1 << 31; // maske = (unsigned int) 1 << 31;

printf("Vorzeichen: ");

if (maske & bit){ //maske & bit filtert das Vorzeichen-Bit heraus; Bitweiser Vergleich; 0 positiv; 1 negativ

printf("1");

vorzeichen = 1;

}

else

{

printf("0");

vorzeichen = 0;

}

printf("\nExponent: ");

exp = 0; //Initialisierung

for (i=0; i<8; i++){ //durchlaufe Schleife bis i=8 --> float: Exponent hat 8 Bits;

maske >>= 1;

exp <<= 1;

if (maske & bit){

exp++;

}

}

exp -= 127; //von exp wird der BIAS-Wert von 127 abgezogen

printf("%d\n", exp);

printf("erweiterte binäre Mantisse: 1."); //1 wird eingefügt, dahinter folgt die reduzierte Mantisse

for (i=0; i<23; i++){ //23 Bits für Mantisse reserviert; IEEE754

maske >>= 1;

if (maske & bit){

printf("1");

}

else {

printf("0");

}

}

//Schritt 1 erledigt: Berechnung Mantisse, Exponent und Vorzeichenbit

//Schritt 2: denormalisieren der Mantisse, dies wird im Binärsystem durch shiften erreicht (dezimal: * 2^3)

//m = x/2^exp

float norm_mantisse = RNOFloat/pow(2.0,exp);

printf("\n\nDezimaldarstellung:\nnormierte Mantisse: %f\n", norm_mantisse);

//Norm. Mantisse = erw. Mantisse dez./2^23

// --> erw. Mantisse dez. = norm. Mantisse * 2^23

int erw_mantisse = norm_mantisse * pow(2.0,23.0);

printf("Erweiterte Mantisse: %d", erw_mantisse);

int den_mantisse = erw_mantisse * pow(2.0,3.0);

printf("\nDenormalisierte Mantisse: %d\n", den_mantisse);

printf("Binaerwert: ");

//Berechnung binäre denorm. Mantisse:

int int_bit_size = 0;

int_bit_size = sizeof(int) * 8;

for(i = 0; i < int_bit_size; i++){

printf("%d", (rest & 0x80000000) >> 31);

rest <<= 1;

}

printf("\n");

char c;

i = 0;

do {

str[i++]= ganzzahl % 10 + '0';

cout << str;

ganzzahl /= 10;

} while (ganzzahl > 0);

str[i--] = '\0';

// reverse order

for (int x = 0, y = i; x<y; x++, y--) {

c = str[x];

str[x] = str[y];

str[y] = c;

}

//Rest

printf("\n");

i=0;

do {

str[i++]= rest % 10 + '0';

cout << str;

rest /= 10;

} while (rest > 0);

str[i--] = '\0';

// reverse order

for (int x = 0, y = i; x<y; x++, y--) {

c = str[x];

str[x] = str[y];

str[y] = c;

}

printf("\n");

}

Ist das soweit richtig?

Geschrieben

Neeeeein, sorry. Ich hab AndiE gemeint mit dem erzwungenen typecast.

Das hilft Dir nicht. Tut mir wirklich leid, ich hätte das besser von Deinem Threadthema abgrenzen müssen.

Du warst zu anfangs schon richtig.

Du darfst das nicht einfach casten, denn das ist nur eine andere Darstellung der 4 bytes, die im Speicher stehen, aber darauf wird keine Mantisse/Exponent etc.

Fakt ist Du musst - wie oben beschrieben - die Mantisse den exponenten und das Vorzeichen aus den 4 bytes des float rausholen. und zwar mit Bitpopelei.

Aber bitte beachte dazu einfach die Dinge, die auf der wiki-Seite stehen.

Ich wäre sogar so frech und würde einfach den float über die angesprochene Bitpobelei in einen Vorkomma- und Nachkomma-Int schreiben und dann mit der Funktion Int_toASCII umwandeln und zusammensetzen :D

Geschrieben

Hallo,

ich habe mal gerechnet:

die Zahl 3,1415926 müßte der uint-zahl "c0 69 0f db"

entsprechen.

mit zahl & 7ffff

bekommst du die normierte Mantisse mit 23 Binärstellen

Ähnlich kannst du dir den Exponenten holen, die Mantisse entsprechend mit einer 1 an 24.Stelle auffüllen(Hidden-bit)

und mit dem Exponenten verschieben.

Vielleicht noch ein kleiner Tipp- Teile die Funktion doch in Unterfunktionen, die jeweils eine Tätigkeit dürchführen- das arbeitet sich nach meiner Erfahrung besser.

LG

André

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...