Forum: Mikrocontroller und Digitale Elektronik Kommazahl in dezimal umwandeln


von Max (Gast)


Lesenswert?

Hallo Leute,

ich bin gerad vor einem rätzel. Wie kann ich die Kommazahl bsp. 0,3 in 
Binär und dann in Dezimal ausgeben?
Kann mir da jemand weiterhelfen?

Danke im Vorraus!

Gruß
Max

von Max (Gast)


Lesenswert?

Natürlich in C!

von Thomas B. (escamoteur)


Lesenswert?

Sorry, aber wie meinst Du das? printf??

von MarioT (Gast)


Lesenswert?

Hallo  Max
>ich bin gerad vor einem rätzel. Wie kann ich die Kommazahl bsp. 0,3 in
>Binär und dann in Dezimal ausgeben?
Das sind wenige Angaben was Du genauer vorhast. Nehme es mal 10 dann ist 
die "0" und das Komma weg(einfach Streichen). Wenn Du es Anzeigen willst 
setzt Du die "0" und das Komma einfach wieder davor.

von Max (Gast)


Lesenswert?

Hallo MaroT,

also genauer möchte ich nach IEEE754 vorgehen. Ich hab einiges vom Code 
geschrieben.
Hasst recht hab es nicht deutlich geschrieben gehabt.
Also ich hab eine Zahl 32,3 und diese möchte ich nach IEEE754 in 
Hexadezimal zahl umwandeln. Ich bin so weit gekommen, dass ich die 
Vordere zahl konvertiert habe. Es fehlt mir nur nachkommazahl. Also in 
prinzip:

0,3 * 2 = 0,6->0
0,6 * 2 = 1,2->1
0,2 * 2 = 0,4->0
0,4 * 2 = 0,8->0
0,8 * 2 = 1,6->1

bin 01001.... und dann in Hex

Sorry einbisschen programmierkenntnisse fehlen mir :(

von Karl H. (kbuchegg)


Lesenswert?

Max schrieb:
> Hallo MaroT,
>
> also genauer möchte ich nach IEEE754 vorgehen. Ich hab einiges vom Code
> geschrieben.
> Hasst recht hab es nicht deutlich geschrieben gehabt.
> Also ich hab eine Zahl 32,3 und diese möchte ich nach IEEE754 in
> Hexadezimal zahl umwandeln.

Du wandelst überhaupt nichts nach 'Hexadezimal'. Hexadezimal ist nur 
eine Schreibweise. Im Rechner ist alles einfach nur 'eine Zahl'. Diese 
Zahl kann man in verschiedenen Repräsentierungen wiedergeben, binär, 
dezimal, hex, aber grundsätzlich ist es einfach nur eine Zahl 
(eigentlich nicht mal das, im eigentlichen Sinne ist es nur ein 
Bitmuster)

> Ich bin so weit gekommen, dass ich die
> Vordere zahl konvertiert habe.

Und wie hast du das gemacht?
Und in welcher Sprache?

> Es fehlt mir nur nachkommazahl. Also in
> prinzip:
>
> 0,3 * 2 = 0,6->0
> 0,6 * 2 = 1,2->1
> 0,2 * 2 = 0,4->0
> 0,4 * 2 = 0,8->0
> 0,8 * 2 = 1,6->1


was mich ein wenig stutzig macht, ist deine konsequente Verwendung eines 
',' für den Dezimalpunkt. In der Programmierung ist ein Dezimalpunkt 
immer ein '.'.

Dies deshalb, weil
* Programmiersprachen aus dem amerikanischen Sprachraum kommen und dort
  ein . üblich ist
* Ein Komma als Aufzählungszeichen benutzt wird (zb um Argumente an
  Funktionen zu trennen)

von MarioT (Gast)


Lesenswert?

Hallo  Max
für einen µC?
für welchen?
hat der Gleitkomma???

von tobi (Gast)


Lesenswert?

Möchtest du eine Gleitpunktzahl einfach nur binär ausgeben?
1
typdef union {
2
    float f_val;
3
    uint32_t i_val;
4
} ftou_t;
5
6
ftou_t foo;
7
foo.f_val = 0.3;
8
9
for(i = 31; i >= 0; --i) {
10
    putc((foo.i_val)&(1<<i) ? '1' : '0');
11
}

Dabei beachten das nicht auf allen Plattformen (z.B. AVR) auch ein 
Double vorhanden ist. Beim AVR ist ein Double ebenfalls nur 32 Bit lang.

von roman65536 (Gast)


Lesenswert?

Max,

schau Dir die konvertierungs routinen an von den gcc compiler.
Der tut genau das, ohne dabei den "float" oder "double" zu verwenden.
von asc->single float, asc->double float etc etc..

Ach ja... suche dir ein alte compiler (pre gcc 3.0) da ist es 
verstaendlicher und der per cpu optimierungs blabla ist nicht dabei. vor 
jahren hatte ich das selber problem, habe damals die konvertierungs 
routine extrahiert und verwendet. (die datei heisst gcc/real.c )

gruss roman

von Max (Gast)


Lesenswert?

Hi MarioT,
ja einen µC von NEC850. Soweit ich weiss Gleitkomma hat er nicht.

von Max (Gast)


Lesenswert?

tobi schrieb:
> Möchtest du eine Gleitpunktzahl einfach nur binär ausgeben?

Danke!
Nein auch in Hexadezimalzahl.

von Mano W. (Firma: ---) (manow)


Lesenswert?

Max schrieb:
> Hi MarioT,
> ja einen µC von NEC850. Soweit ich weiss Gleitkomma hat er nicht.

Damit meinst Du wohl das er keine FPU hat? Einen C-Compiler und eine 
standard C Bib. hast Du aber schon, oder?

von henky (Gast)


Lesenswert?

Max schrieb:
> tobi schrieb:
>> Möchtest du eine Gleitpunktzahl einfach nur binär ausgeben?
>
> Danke!
> Nein auch in Hexadezimalzahl.
Weißt du wie eine Fließkommazahl binär aussieht?

von MarioT (Gast)


Lesenswert?

Hallo  Max
>ich bin gerad vor einem rätzel. Wie kann ich die Kommazahl bsp. 0,3 in
>Binär und dann in Dezimal ausgeben?
>Soweit ich weiss Gleitkomma hat er nicht.
Ist doch schon die halbe Antwort. Was nicht geht geht halt nicht.
Kannst Du es nicht so machen wie ich oben schon geschrieben habe?
Karl heinz Buchegger schrieb
>... im eigentlichen Sinne ist es nur ein Bitmuster)
Du willst doch das der µC etwas rechnet, ob da ein Komma ist oder nicht 
interessiert doch keinen. Mußt ihm nur die "Zahlen" so geben das er es 
richtig macht(wenn z.B "+1" dann mußt Du wenn es eine Kommastelle war 
halt mit 10 addieren). Wenn Du die Zahlen wieder nach Dezimal wandelst 
machst Du einfach das Komma an der richtigen Stelle wieder rein. Du 
kannst damit deinem µC viel Arbeit abnehmen.
>auch in Hexadezimalzahl
Gehe mal davon aus, das es nur Bit giebt.
Hexadezimalzahl schreibt man nur das es schöner aussieht wegen der 
vielen Nullen und Einsen. Ein Prozessor weiß nicht was Du von ihm 
willst.
henky schrieb
>Weißt du wie eine Fließkommazahl binär aussieht?
oder Hexadezimalzahl?
Das einzige was möglich ist jedes Byte mit ASCII anzuzeigen.

von henky (Gast)


Lesenswert?

MarioT schrieb:
>>Weißt du wie eine Fließkommazahl binär aussieht?
> oder Hexadezimalzahl?
> Das einzige was möglich ist jedes Byte mit ASCII anzuzeigen.
Er kann ja auch die Mantisse und Co. rauspulen und und angeben... wenn 
sein Lehrer das so möchte. ;-)

von Karl H. (kbuchegg)


Lesenswert?

Die wichtigste Frage ist für mich:
In welcher Sprache soll das ganze abgehandelt werden?

Wenn es C ist UND ein Compiler zur Verfügung steht, der bereits IEEE754 
macht, dann ist die Aufgabe ziemlich trivial. Wenn man aber mehr oder 
weniger, die Floating Point Library, die der Compiler mitbringt, nicht 
benutzen kann, dann wirds aufwändig. Dann muss man erst mal damit 
anfangen, sich die Basisfunktionen in IEEE754-Floating Point für 
Addition, Multiplikation und Division zu schreiben. Hat man die erst mal 
fertig, wirds wieder einfacher. Man kann dann zwar nicht mehr direkt 
schreiben

   result = 10 * result + nextDigit;

sondern muss das durch entsprechende Aufrufe in diese Basislibrary 
ersetzen. Das Prinzip bleibt allerdings nach wie vor dasselbe.

Vorkommateil:

   result = 10 * result + nextDigit;

Nachkommateil:

   result = result + nextDigit * stelle;
   stelle /= 10;

Die einzigen Floating Point Konstanten, deren Byte-Repräsentierung man 
kennen muss, sind 1 und 10

von henky (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Die wichtigste Frage ist für mich:
> In welcher Sprache soll das ganze abgehandelt werden?
Das hat Max im zweiten Post verraten. ;-)
Max schrieb:
> Natürlich in C!

Karl heinz Buchegger schrieb:
> Wenn es C ist UND ein Compiler zur Verfügung steht, der bereits IEEE754
> macht, dann ist die Aufgabe ziemlich trivial. Wenn man aber mehr oder
> weniger, die Floating Point Library, die der Compiler mitbringt, nicht
> benutzen kann, dann wirds aufwändig.
Das hat Max noch nicht verraten.
Ansonsten, keine Ahnung von so was, ich glaube dir einfach mal. ;-)

von Karl H. (kbuchegg)


Lesenswert?

henky schrieb:
> Karl heinz Buchegger schrieb:
>> Die wichtigste Frage ist für mich:
>> In welcher Sprache soll das ganze abgehandelt werden?
> Das hat Max im zweiten Post verraten. ;-)
> Max schrieb:
>> Natürlich in C!

Mein Fehler. Hab ich überlesen.

> Karl heinz Buchegger schrieb:
>> Wenn es C ist UND ein Compiler zur Verfügung steht, der bereits IEEE754
>> macht, dann ist die Aufgabe ziemlich trivial. Wenn man aber mehr oder
>> weniger, die Floating Point Library, die der Compiler mitbringt, nicht
>> benutzen kann, dann wirds aufwändig.
> Das hat Max noch nicht verraten.
> Ansonsten, keine Ahnung von so was, ich glaube dir einfach mal. ;-)

Ich dachte auch immer, dass das wahsinnig aufwändig sei und bin vor 
dieser Aufgabe gestanden, wie der Ochs vorm Tor.
Bis ich dann den Code eines professionellen Pascal-Compilers in die 
Finger bekam. Natürlich suchte ich die betreffende Stelle und machte 
mich darauf gefasst, da auf eine Byteorgie zu stossen.

Aber Pustekuchen: Das war eine ganz normale Zahleneinleseroutine, so wie 
man sie macht, wenn man von einer Seriellen einen ASCII-Text 
hereinbekommt. Und da ist es mir dann gedämmert. Die Byte-Orgie braucht 
nicht im Pascal-Quelltext stehen, weil sie der compilierende Pascal 
Compiler schon beherrscht. Damit hat man dann das Henne-Ei Problem. Im 
allerersten Compiler muss man die normale Schreibweise gegen eine mit 
direkten Library Aufrufen ersetzen und die vorkommenden Konstanten (sind 
nur 1 und 10) einmal händisch in ihre Floating-Point Byte Form 
übersetzen, sofern es keine int->float Funktion gibt). Sobald aber der 
Urcompiler soweit steht, dass er das alles übersetzen kann, wird das 
dann im Zuge des Bootstrap-Prozesses durch den endgültigen, einfachen 
Code ersetzt.

Daher die Fragestellung: Worauf kann man aufbauen? Steht ein C-Compiler 
zur Verfügung, dessen Floating Point Behandlung mitbenutzt werden darf 
oder nicht?

Wenn ja, dann zb so (ohen Behandlung von Exponenten und Vorzeichen)
1
double readFloat( const char* text )
2
{
3
  double result = 0.0;
4
  double fraction = 1.0;
5
6
  while( *text &&
7
         *text != '.' &&
8
         ( *text >= '0' && *text <= '9' )
9
    result = 10 * result + ( *text - '0' );
10
11
  if( *text != '.' )
12
    return result;
13
14
  while( *text &&
15
         *text >= '0' && *text <= '9' ) {
16
    fraction /= 10.0;
17
    result = result + ( *text - '0' ) * fraction;
18
  }
19
20
  return result;
21
}

Eine andere Möglichkeit wäre es, den Nachkommaanteil ebefalls zunächst 
als normale ganze Zahl einzulesen und dabei die Anzahl der Stellen 
mitzuzählen, damit die Division zur Verschiebung in den Nachkommaanteil 
erst ganz zum Schluss gemacht werden kann.

von Max (Gast)


Lesenswert?

Hallo Leute,

Danke für eure hilfe!
Ich hab es ma so gemacht und es funktioniert wunderbar :D

tobi schrieb:
> typdef union {
>
>     float f_val;
>
>     uint32_t i_val;
>
> } ftou_t;
>
>
>
> ftou_t foo;
>
> foo.f_val = 0.3;
>
>
>
> for(i = 31; i >= 0; --i) {
>
>     putc((foo.i_val)&(1<<i) ? '1' : '0');
>
> }

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.