Forum: Compiler & IDEs Floating Point, Mantisse, Exponent - Beispiele?


von Gast (Gast)


Lesenswert?

http://de.wikipedia.org/wiki/Gleitkommazahl

Wie geht man mit floating point Variablen um? Werden die Zahlen 
normiert? Kann man auf den Exponenten direkt zugreifen?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Gast schrieb:

> Wie geht man mit floating point Variablen um?
1
const double pi = 3.1415926;
2
3
double area(double r)
4
{
5
  return 4 * pi * r * r;
6
}

> Werden die Zahlen
> normiert?

Ja, außer ganz kleine Zahlen (und ganz große auch? bin ich mir
gerade nicht sicher), die werden denormiert gespeichert, damit man
sie überhaupt noch darstellen kann.

> Kann man auf den Exponenten direkt zugreifen?

Nein, nicht ohne Tricks[*], warum auch?

[*] Bei 32-bit-Gleitkomma belegt der Exponent ja genau ein Byte,
da könnte man ihn durch Überlagern einer union extrahieren.  Bei
64-bit-Gleitkomma geht das auch nicht mehr.

Es gibt die Funktion frexp() in der math-Bibliothek, die einem
Mantisse und Exponent separiert.

von Oliver (Gast)


Lesenswert?

>Wie geht man mit floating point Variablen um?

Man überlässt es dem Compiler bzw. der mathe-lib, damit zu rechnen.

>Werden die Zahlen normiert?

Ja

>Kann man auf den Exponenten direkt zugreifen?

Klar. Caste den float in einen unsigned int passender Größe, und 
maskiere die entsprechenden Bits aus, dann noch etwas shiften, schon 
hast du Exponent und Mantisse.

Bleibt die Frage:

Was hast du eigentlich vor?

Oliver

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Oliver schrieb:

> Klar. Caste den float in einen unsigned int passender Größe, und
> maskiere die entsprechenden Bits aus, dann noch etwas shiften, schon
> hast du Exponent und Mantisse.

Nein.  Du hast den ganzzahligen Wert oder dessen unsigned-Darstellung
(wenn er negativ war), so, wie du es beschrieben hast.  Anders als
bei Ganzzahlen bewirkt ein typecast bei Gleitkommazahlen eine echte
Typumwandlung, nicht nur ein Uminterpretieren des Bitmusters.  (Selbst
bei Ganzzahlen erfolgt dieses Uminterpretieren nur beim typecast
zwischen signed und unsigned.)

von Martin Cibulski (Gast)


Lesenswert?

Man müsste einen Pointer umcasten, dann könnte man auf das Bitmuster 
direkt zugreifen.

Etwa so:

unsigned long lVar;
float         fVar = 1.234;

lVar = *((unsigned long*)&fVar);


Gruß,
Martin Cibulski

von yalu (Gast)


Lesenswert?

In C (C99) liefert die Funktion

  m = frexp(x, e)

für die Zahl x die Mantisse m und den ganzzahligen Exponenten e so dass

  x = m * 2**e    und   0.5 <= |m| < 1

ist.

von yalu (Gast)


Lesenswert?

Ach, das hat ja Jörg oen schon geschrieben.

von P. S. (Gast)


Lesenswert?

Jörg Wunsch schrieb:

>> Kann man auf den Exponenten direkt zugreifen?
> Nein, nicht ohne Tricks[*], warum auch?

Der von Martin beschrieben Pointer-cast funktioniert (was man wohl als 
Trick bezeichnen kann). Der Grund fuer sowas ist einfach: Moeglichst 
verlustarme Transformierung in andere Zahlenformate.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter Stegemann schrieb:

> Der von Martin beschrieben Pointer-cast funktioniert (was man wohl als
> Trick bezeichnen kann).

Wie ich oben schon schrieb, bedingt: die 11-bittige Mantisse einer
64-bit-Zahl nach IEEE 754 popelst du mit diesem Trick auch nicht
mehr raus, zumindest nicht ohne Nachbearbeitung (maskieren/schieben).

Edit: OK, wofür ein solcher Trick brauchbar sein kann ist, dass man
sich das Bitmuster, das zu einer bestimmten Gleitkommazahl gehört,
mal ansehen kann (gewissermaßen die Zerlegung in Mantisse und
Exponent dann im Gehirn macht).

von P. S. (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> Peter Stegemann schrieb:

>> Der von Martin beschrieben Pointer-cast funktioniert (was man wohl als
>> Trick bezeichnen kann).
> Wie ich oben schon schrieb, bedingt: die 11-bittige Mantisse einer
> 64-bit-Zahl nach IEEE 754 popelst du mit diesem Trick auch nicht
> mehr raus, zumindest nicht ohne Nachbearbeitung (maskieren/schieben).

Das man das Bitmuster noch gemaess Standard interpretieren und zerlegen 
muss, ist ja wohl klar.

> Edit: OK, wofür ein solcher Trick brauchbar sein kann ist, dass man
> sich das Bitmuster, das zu einer bestimmten Gleitkommazahl gehört,
> mal ansehen kann (gewissermaßen die Zerlegung in Mantisse und
> Exponent dann im Gehirn macht).

seufz. Nur weil du es nicht brauchst, heisst das nicht, dass es fuer 
andere keinen Sinn ergibt, sowas zu machen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter Stegemann schrieb:

> Nur weil du es nicht brauchst, heisst das nicht, dass es fuer
> andere keinen Sinn ergibt, sowas zu machen.

Die Frage des OP war aber: "Kann man auf den Exponenten direkt
zugreifen?"

Aber der meldet sich sowieso nicht mehr, wie's scheint.

von Gast (Gast)


Lesenswert?

Doch, danke für die Hinweise!
Es geht um die Darstellung von physikalischen Größen, ich hatte 
angedacht, eine Art auto-ranging mit Präfixumschaltung zu realisieren.

Man kann natürlich auch einfach den Wert mit den entsprechenden 10er 
Potenzen vergleichen und ggf. den Format-String für printf anpassen.

von Karl H. (kbuchegg)


Lesenswert?

Gast schrieb:

> Man kann natürlich auch einfach den Wert mit den entsprechenden 10er
> Potenzen vergleichen und ggf. den Format-String für printf anpassen.

Eindringliche Warnung:
Mach es genau so und vergiss dass ein double intern als 
Mantisse+Exponent gespeichert wird.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Gast schrieb:

> Man kann natürlich auch einfach den Wert mit den entsprechenden 10er
> Potenzen vergleichen und ggf. den Format-String für printf anpassen.

Das ist zweifellos die sinnvollste Variante.  Nicht nur, dass sie
nicht von der konkreten Zahlendarstellung abhängig ist, sondern
jemand, der das Programm hinterher liest, kann das sogar noch
verstehen. ;-)

Hier mal ein Schnipsel aus einem real existierenden Programm, in
dem ich sowas schon gemacht habe:
1
      double f = freq;
2
3
      if (f > 1E6)
4
        {
5
          fmt_freq[7] = 'M';
6
          f /= 1E6;
7
        }
8
      else if (f > 1E3)
9
        {
10
          fmt_freq[7] = 'k';
11
          f /= 1E3;
12
        }
13
      else
14
        {
15
          fmt_freq[7] = ' ';
16
        }
17
      sprintf(b, fmt_freq, f);
18
      hd44780_outcmd(HD44780_DDADDR(LCD_LINE1));

von Karl H. (kbuchegg)


Lesenswert?

Jörg Wunsch schrieb:
> Gast schrieb:
>
>> Man kann natürlich auch einfach den Wert mit den entsprechenden 10er
>> Potenzen vergleichen und ggf. den Format-String für printf anpassen.
>
> Das ist zweifellos die sinnvollste Variante.  Nicht nur, dass sie
> nicht von der konkreten Zahlendarstellung abhängig ist, sondern
> jemand, der das Programm hinterher liest, kann das sogar noch
> verstehen. ;-)

Und es wird auch funktionieren.
Ich denke nicht, dass der TO daran gedacht hat, dass der Exponent ein 
Exponent zur Basis 2 ist und nicht zur Basis 10, wodurch seine ganze 
Idee mit direktem Zugriff auf den Exponenten in der angedeuteten 
Problemstellung alles andere als simpel sein würde :-)

von Gast (Gast)


Lesenswert?

Konnte ich auch nicht, denn die 
http://de.wikipedia.org/wiki/Gleitkommazahl#Interne_Darstellung kannte 
ich gar nicht :-)

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.