Floating Point, Mantisse, Exponent - Beispiele?

Moderator Persönliche Seite
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.
Gast
>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
Moderator Persönliche Seite
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.)
Gast
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
Gast
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.
Gast
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.
Moderator Persönliche Seite
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).
Gast
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.
Gast
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.
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.
Moderator Persönliche Seite
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));
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 :-)

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 16 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.