Forum: Mikrocontroller und Digitale Elektronik uint32_t => float (32) ohne cast!


von Ralf (Gast)


Lesenswert?

Moin!

Also, ich habe im externen Speicher feste Variablen hinterlegt. Über 4 
Bytes liegt dort ein float (0.007964 bzw. 0x3c027b70). Meine 
Lese-Funktion übergibt mir das ganze als uint32_t. Wie bekomme ich das 
nun in einem float gespeichert ohne, dass das Ding umgerechnet bzw. 
gecastet wird?

Pseudocode:

float myFloat = lese_speicher(adresse); //lese_speicher übergibt 
uint32_t

danach steht in myFloat 1006795632.

gibt es da eine Möglichkeit, oder muss ich mir dafür eine neue 
Lesefunktion basteln?

von Einer K. (Gast)


Lesenswert?

Ralf schrieb:
> Meine
> Lese-Funktion übergibt mir das ganze als uint32_t.
Warum tut sie das?

Vielleicht suchst du "UNION"

Ralf schrieb:
> gibt es da eine Möglichkeit, oder muss ich mir dafür eine neue
> Lesefunktion basteln?

Würde ich dir empfehlen.

von Ralf (Gast)


Lesenswert?

Weil ich bis auf eben diese eine Variable ausschließlich Integer auf dem 
Speicher liegen habe. Es ist natürlich kein Problem eine neue Funktion 
zu erstellen, aber ich dachte es geht irgendwie "einfacher".

von CC (Gast)


Lesenswert?

1
float *f = &var_uint_32;
2
3
printf("float = %f\n", *f);
(ungetestet)

von Ralf (Gast)


Lesenswert?

CC schrieb:
> float *f = &var_uint_32;
>
> printf("float = %f\n", *f);
> (ungetestet)

ja, so gehts natürlich auch! :D

von Peter II (Gast)


Lesenswert?

Ralf schrieb:
> ja, so gehts natürlich auch! :D

Außen wenn das Alignment für float anders ist als für int32. Dann knallt 
es bei zugriff auf das float.

von André R. (andr_r619)


Lesenswert?

Geht eigentlich nur über einen Cast, wenn Du keine zweite Lesefunktion 
erstellen willst. Ich weiß leider nicht, inwieweit man mit C generische 
Funktionen* entwickeln kann; das wäre nämlich eine zweite Möglichkeit.

*https://de.wikipedia.org/wiki/Generische_Programmierung

von Alex E. (tecnologic) Benutzerseite


Lesenswert?

memcpy(&int, &float, sizeof(float));

von Nop (Gast)


Lesenswert?

CC schrieb:
> float *f = &var_uint_32;
>
> printf("float = %f\n", *f);
> (ungetestet)

Das ergibt undefiniertes Verhalten laut C-Standard.

von Noch einer (Gast)


Lesenswert?

Von John Carmack, dem Meister aller Tricksereien stammt:

y = * ( float * ) &i;

https://www.heise.de/newsticker/meldung/Zahlen-bitte-0x5f3759df-merkwuerdige-Mathematik-im-Egoshooter-3208927.html

von Daniel A. (daniel-a)


Lesenswert?

Ich habe mal, weil mir die ganzen Hacks nicht gefallen haben, folgende 
Library geschrieben:
https://github.com/Daniel-Abrecht/IEEE754_binary_encoder

von Ralf (Gast)


Lesenswert?

danke noch mal!

also, das mit dem pointer funktioniert´s zwar, aber es gibt eine 
warnung! es könnte also probleme geben.

habe endgültig mit memcpy eine lesefunktion geschrieben, die mir dann 
auch einfach ein float zurück gibt. feddisch... :)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Noch einer schrieb:
> Von John Carmack, dem Meister aller Tricksereien stammt:

Pfusch. Das ist ganz sicher nicht das gewünschte.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Rufus Τ. F. schrieb:
> Noch einer schrieb:
>> Von John Carmack, dem Meister aller Tricksereien stammt:
>
> Pfusch. Das ist ganz sicher nicht das gewünschte.

"Trickserei" ist eine Obermenge von "Undefined Behaviour" ;-)

von Stefan F. (Gast)


Lesenswert?

> y = * ( float * ) &i;
> Pfusch. Das ist ganz sicher nicht das gewünschte.

Warum nicht? Ich finde diese Lösung total naheliegend.

von Adam P. (adamap)


Lesenswert?

Stefan U. schrieb:
> Warum nicht? Ich finde diese Lösung total naheliegend.

Sehe ich auch so...

Wenn ich 4 Byte im Speicher habe kann ich diese doch interpretieren wie 
ich möchte.

Ob als float, int oder sogar struct.

Oder spricht etwas gegen diese Ansicht?

von Peter II (Gast)


Lesenswert?

Adam P. schrieb:
> Oder spricht etwas gegen diese Ansicht?

das es Systeme gibt, die eine Ausrichtung der Daten im Speicher 
brauchen. Sie können nicht ein float an beliebiger Adresse verarbeiten.

von Markus F. (mfro)


Lesenswert?

Peter II schrieb:
> das es Systeme gibt, die eine Ausrichtung der Daten im Speicher
> brauchen. Sie können nicht ein float an beliebiger Adresse verarbeiten.

Zum Beispiel?

Natürlich nur Plattformen bei denen ein float auch wirklich 32 Bit hat.

von Karl (Gast)


Lesenswert?

Adam P. schrieb:
> Oder spricht etwas gegen diese Ansicht?

Gegen diese Ansicht spricht nichts, wir haben ja Meinungsfreiheit.

Ein geneigter C-Compiler könnte sich aber weigern das zu tun, was du 
erwartest, weil die Strict-Aliasing-Rules verletzt werden. Einfach 
gesprochen muss der Compiler den zugriff nicht ausführen, wenn Du an 
eine Stelle zuletzt nicht den Typ geschrieben hast, den Du lesen 
möchtest. Eine Union funktioniert hier auch nicht (garantiert). Ausnahme 
sind alle Arten von char.

Sprich: Eine Union von uint32_t nach uint8_t[] und zurück wäre erlaubt, 
von uint32_t nach float aber nicht.

Das Konstrukt mit memcpy ist eine weithin akzeptierte Lösung, die der 
Compiler normalerweise laufzeitneutral wegoptimiert.

von Adam P. (adamap)


Lesenswert?

Ja OK, das der Compiler da vllt. dann nicht mitspielt ist eine andere 
Geschichte, ebenfalls das mit dem wegoptimieren.

Aber wenn der Compiler brav macht, was man in C geschrieben hat, sollte 
es doch kein Problem geben.

(Hab es mit dem gcc ausprobiert - embedded und linux) -> soweit alles 
OK.

von Peter II (Gast)


Lesenswert?

Markus F. schrieb:
> Natürlich nur Plattformen bei denen ein float auch wirklich 32 Bit hat.

das Floats nicht an ungeraden Adressen liegen dürfen gibt es sehr oft. 
Aber ob es Systeme gibt, wo es unterschiedliche Ausrichtungen für int 
und float gibt kann ich nicht sagen.

von Mampf F. (mampf) Benutzerseite


Lesenswert?

Daniel A. schrieb:
> Ich habe mal, weil mir die ganzen Hacks nicht gefallen haben, folgende
> Library geschrieben:
> https://github.com/Daniel-Abrecht/IEEE754_binary_encoder

Ööööh ... wofür soll das gut sein?

32 und 64Bit Float-Zahlen haben doch eine eindeutige binäre 
Repräsentation ... Was spricht gegen casten?

von Markus F. (mfro)


Lesenswert?

beim gcc braucht's u.U. ein -fno-strict-aliasing (nach dem -O2/-Ox, 
sonst schaltet das wieder ein).

memcpy() ist aber die sauberere Lösung.

von Stefan F. (Gast)


Lesenswert?

Kann man das strict aliasing nicht durch einen void* umgehen?

von Peter II (Gast)


Lesenswert?

Stefan U. schrieb:
> Kann man das strict aliasing nicht durch einen void* umgehen?

klar kann man das, aber es sind ja nicht ohne Grund drin. Es kann dann 
zu Problemen kommen.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Stefan U. schrieb:
>> y = * ( float * ) &i;
>> Pfusch. Das ist ganz sicher nicht das gewünschte.
>
> Warum nicht? Ich finde diese Lösung total naheliegend.

Type Punning.

https://blog.regehr.org/archives/959

http://mail-index.netbsd.org/tech-kern/2003/08/11/0001.html

von Nop (Gast)


Lesenswert?

Adam P. schrieb:

> Aber wenn der Compiler brav macht, was man in C geschrieben hat

Das ist aber kein C, also darf der Compiler damit tun, was immer er 
will. Wenn nicht jetzt, dann nach dem nächsten Compiler-Update. Das ist 
dann ein Spaß mit der Fehlersuche.

von asdfasd (Gast)


Lesenswert?

Strict aliasing in C ist, als wenn man nen Lichtschalter unter Strom 
setzt und nen Schild drüber hängt "Nur mit Gummihandschuhen betätigen!".

Glücklicherweise gibt es "-fno-strict-aliasing" ...

von Nico W. (nico_w)


Lesenswert?

Quake hat ja auch funktioniert. Muss man halt immer sehen wo ich das 
genau wie einsetzen will.

https://en.wikipedia.org/wiki/Fast_inverse_square_root#Overview_of_the_code

von Einer K. (Gast)


Lesenswert?

In der Arduinowelt könnte man den Mist auch so schreiben:
1
float uint32ToFloat(uint32_t value)
2
{
3
  union
4
  {
5
    uint32_t  asUint;
6
    float     asFloat;  
7
  } konverter;
8
  konverter.asUint=value;
9
  return konverter.asFloat;
10
}
11
12
void setup() 
13
{
14
  Serial.begin(9600);
15
  uint32_t testwert = 0x3c027b70UL;
16
  Serial.println(uint32ToFloat(testwert),6);
17
}
18
19
void loop() 
20
{
21
}

In der Hoffnung, dass man das niemals sonst noch braucht, habe ich die 
Vereinigung lokal und anonym gemacht.

von Nop (Gast)


Lesenswert?

asdfasd schrieb:
> Strict aliasing in C ist, als wenn man nen Lichtschalter unter Strom
> setzt und nen Schild drüber hängt "Nur mit Gummihandschuhen betätigen!".

Hat aber einen guten Grund, weil der Compiler sonst nach jedem 
Schreibzugriff über irgendeinen Pointer sämtliche anderen Variablen neu 
laden müßte - sie könnten sich ja geändert haben.

So betrifft diese Misere nur Variablen eines zum Pointer kompatiblen 
Typen, was ein wichtiger Grund ist, wieso C bei Numerik langsamer als 
Fortran ist, welches gar kein Aliasing erlaubt. Das kann man aber seit 
C99 auch abstellen, indem man den Pointer mit restrict behaftet.

Ob das allerdings überhaupt Auswirkungen auf die Performance hat, kommt 
sehr auf den konkreten Code an. Er muß dazu pointer- und rechenintensiv 
sein, und er muß die Rechenergebnisse auch in die Pointerbereiche 
schreiben und wieder lesen.

Wenn man hingegen eher Idiome verwendet, bei denen man aus 
Pointerbereichen liest, mit funktionslokalen Variablen rechnet und das 
am Ende zurückschreibt, wird man keine Auswirkungen bemerken.

von Daniel A. (daniel-a)


Lesenswert?

Mampf F. schrieb:
> Daniel A. schrieb:
>> Ich habe mal, weil mir die ganzen Hacks nicht gefallen haben, folgende
>> Library geschrieben:
>> https://github.com/Daniel-Abrecht/IEEE754_binary_encoder
>
> Ööööh ... wofür soll das gut sein?
>
> 32 und 64Bit Float-Zahlen haben doch eine eindeutige binäre
> Repräsentation ... Was spricht gegen casten?

Eine CPU Architektur muss nicht zwingend IEEE 754 für floating point 
Operationen, verwenden, und ein float muss nicht zwingend 32bit gross 
sein. Auch bit und byte order können unterschiedlich sein. Solange man 
keine Daten zwischen unterschiedlichen Systemen austauscht wäre 
zumindest memcpy akzeptabel, falls in ein uint32_t aber nur, wenn man 
noch ein static_assert(sizeof(float)==sizeof(uint32_t),"Float wasn't 4 
bytes big"), einbaut. Bei einem cast ist nur nach char* in Ordnung, 
wegen aliasing.
Wenn man jedoch zwischen verschiedenen Geräten Daten austauschen will, 
muss man sicherstellen, dass diese auf allen möglichen Plattformen 
identisch gelesen und geschrieben werden, und das ist wofür man diese 
Library brauchen kann. Wenn du z.B. auf einem x86 little endian System 
einen float einfach casten würdest, hättest du, obwohl x86 IEEE 754 
verwendet, die bytes in little endian statt in network byte order aka 
big endian.

Ich versuche meinen Code immer so zu schreiben, dass er 
Programmunabhängig ist. Ich versuche möglichst nie annahmen zu Sachen zu 
machen, die nicht garantiert sind zu funktionieren, so etwas ist einfach 
Murks, und falls es doch mal nicht anders geht, füge ich zumindest einen 
compile time check zur Überprüfung der Annahme hinzu. Plattform 
spezifisches sollte nur an einer möglichst kleinen stelle verwendet 
werden, sofern man das Plattform spezifisches unbedingt verwenden muss, 
den Rest kann man abstrahieren. Damit erspart man sich auch später das 
suchen von scheinbar unerklärlichen Fehlern.

Beitrag #5111357 wurde vom Autor gelöscht.
von Mampf F. (mampf) Benutzerseite


Lesenswert?

Amüsanter akademischer Ansatz, aber leicht an der Realität vorbei, denke 
ich :)

Für meinen Geschmack ist die Komplexität für ein triviales Problem zu 
hoch :)

Nicht IEEE754-Floats kommen in der Praxis doch so gut wie nicht vor und 
die Little- und Big-Endian Problematik wurde doch schon mehrfach gelöst 
(zB Network-Endianess und die passenden Konvertierungsfunktionen).

Die Lib unterstützt auch garnichts anderes außer einer Endian-Art und 
nur IEEE754.

Und Buggy ist sie auch:

> Subnormal floating point values (values really close to zero) are
> truncated to zero for simplicity reasons. I may change this someday.

Da kann von allgemeingültiger Ansatz eigentlich keine Rede sein.

In wie weit das besser sein soll als ein

float f = *((float*) &u);

erschließt sich mir daher nicht.

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Mampf F. schrieb:
> Für meinen Geschmack ist die Komplexität für ein triviales Problem zu
> hoch :)
>
> Die Lib unterstützt auch garnichts anderes außer einer Endian-Art und
> nur IEEE754.
>
> Und Buggy ist sie auch:

Das ist folgendes aber auch, lies einfach oben:

> float f = *((float*) &u);

Ich versteh echt nicht warum einige hier so an einer offenbar falschen 
Lösung kleben wie am Fliegenleim, wo der korrekte Ansatz via memcpy doch 
bereits gegeben wurde — und gefühlt mindestens 1x pro Monat hier wieder 
und wieder aufs Tablett kommt.

Was ist das Problem bei memcpy?  Die 6 zu tippenden Buchstaben wohl 
kaum...

Arduino F. schrieb:
>   union
>   {
>     uint32_t  asUint;
>     float     asFloat;
>   } konverter;
>   konverter.asUint=value;
>   return konverter.asFloat;

Auch falsch.

Beim Lesen von .asFloat kann der Compiler davon ausgtehen, das Schreiben 
auf .asUint die inkompatible Komponente .asFloat nicht verändert.

Dieses "Type Punning per Union" wird zwar von GCC unterstützt (steht 
irgendwo im Kleingedruckten), konformes C ist es aber nicht.

Nochmal: Was ist so schlimm an memcpy? Ist hier sogar weniger zu tippen.

Aus z.B.
 
1
#include <stdint.h>
2
#include <string.h>
3
4
static inline float asFloat (uint32_t i)
5
{
6
    float f;
7
    memcpy (&f, &i, sizeof f);
8
    return f;
9
}
10
11
static inline uint32_t asUInt (float f)
12
{
13
    uint32_t i;
14
    memcpy (&i, &f, sizeof i);
15
    return i;
16
}
17
18
float nextFloat (float f)
19
{
20
    return asFloat (1 + asUInt (f));
21
}

macht avr-gcc -Os
1
nextFloat:
2
  subi r22,-1
3
  sbci r23,-1
4
  sbci r24,-1
5
  sbci r25,-1
6
  ret
 
getestet mit v8, v7, v6, v5, v4.9, v4.8. v4.7, v4.6 und WinAVR-20100110.

von Peter II (Gast)


Lesenswert?

Johann L. schrieb:
> macht avr-gcc -Os

man sollte die Funktionen aber schon aufrufen.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Peter II schrieb:
> Johann L. schrieb:
>> macht avr-gcc -Os
>
> man sollte die Funktionen aber schon aufrufen.

Man sollte den Quellcode schon lesen:

Johann L. schrieb:
> float nextFloat (float f)
> {
>     return asFloat (1 + asUInt (f));
> }

von Peter II (Gast)


Lesenswert?

Johann L. schrieb:
> Man sollte den Quellcode schon lesen:

und wo wird nextFloat aufgerufen

von Stefan F. (Gast)


Lesenswert?

Ich verstehe nicht, wieso memcpy() besser sein soll, als einen Pointer 
zu casten. Im gegenteil, es ist unnötiger Overhead.

Wenn ich davon ausgehe, daß die vier Bytes einem Float entsprechen dann 
ist das Casten des Pointers effektiver. Durch den memcpy() Ansatz 
kopiere ich letztendlich den Speicher UND caste des Datentyp. Was soll 
daran besser sein?

Die Annahme, daß die vier Bytes ein Float seien, ist fragwürdig. Nur 
mach memcpy() die Sache kein bisschen sicherer.

von Peter II (Gast)


Lesenswert?

Stefan U. schrieb:
> Ich verstehe nicht, wieso memcpy() besser sein soll, als einen Pointer
> zu casten. Im gegenteil, es ist unnötiger Overhead.

es stellt das Alignment sicher.

Und der Overhead verschwindet, wenn der Compiler sinnvoll optimiert.

von Nop (Gast)


Lesenswert?

Johann L. schrieb:

> Dieses "Type Punning per Union" wird zwar von GCC unterstützt (steht
> irgendwo im Kleingedruckten), konformes C ist es aber nicht.

Seit C99 schon, und das ist doch default beim GCC.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Stefan U. schrieb:
> Wenn ich davon ausgehe, daß die vier Bytes einem Float entsprechen dann
> ist das Casten des Pointers effektiver.

Was nutzt effektiver Code wenn er falsch ist.

> Ich verstehe nicht, wieso memcpy() besser sein soll, als einen Pointer
> zu casten. Im gegenteil, es ist unnötiger Overhead.

Hast du ein konkretes Beispiel?

von Nop (Gast)


Lesenswert?

Stefan U. schrieb:
> Durch den memcpy() Ansatz kopiere ich letztendlich den Speicher

Nur, wenn Du keine Compiler-Optimierungen aktiv hast, und dann ist 
Performance offensichtlich sowieso egal. Ansonsten erlaubt die generelle 
as-if-Philosophie dem Compiler, das memcpy komplett wegzuoptimieren. Da 
wird dann keine Funktion aufgerufen und kein Speicher kopiert.

von Mikro 7. (mikro77)


Lesenswert?

Stefan U. schrieb:
> Ich verstehe nicht, wieso memcpy() besser sein soll, als einen Pointer
> zu casten. Im gegenteil, es ist unnötiger Overhead.

Für Leute, die aus der "Assemblerwelt" kommen, ist das natürlich 
Blödsinn. Ich habe 4 Bytes im Speicher und ob ich die als Ganz- oder 
Gleitkommzahl verwende ist meine Sache.

C führt eine Abstraktionsebene ein. Ein Variable ist nicht einfach eine 
typisierte Adresse im Speicher die ein paar Bytes belegt. Es sind auch 
verschiedene Regeln mit dieser Variablen verbunden. Eine davon ist das 
(verbotene) Aliasing.

http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html

von Johnny B. (johnnyb)


Lesenswert?

Mach einfach einen cast auf float und fertig. Sehe da für Deine 
Anwendung 0 Probleme.

von Peter II (Gast)


Lesenswert?

Johnny B. schrieb:
> Mach einfach einen cast auf float und fertig. Sehe da für Deine
> Anwendung 0 Probleme.

und warum nicht gleich richtig machen? ein memcpy macht auch 0 Probleme.

von Darth Moan (Gast)


Lesenswert?

Moin,

Peter II schrieb:
> und warum nicht gleich richtig machen? ein memcpy macht auch 0 Probleme.

ich bin erst sehr kurz beim GCC. Hab das grad mal ausprobiert, und bin
regelrecht begeistert, dass der GCC das memcpy tatsaechlich ganz
rausschmeist und durch was sinnvolles ersetzt. Bisher hatte ich immer
andere Target Compiler. Und da hatte ich das bisher nicht erlebt.
Allerdings hatte ich vorher noch nie alle Optionen selbst unter
Kontrolle. Die waren haeufig vorgegeben (und scheinbar in Stein
gemeisselt). Wenn das memcpy nicht ersetzt wird, ist das schon ziemlich
unperformant.
Jedenfalls auf kleineren cores. Ja, die haben meistens keine floats in
HW, aber das gilt ja allgemein fuer verschiedene Datentypen. Und auf
kleinen Cores ist memcpy einfach extrem lahm und somit "Teufelszeug".

Gut zu wissen.
Danke

von Stefan F. (Gast)


Lesenswert?

Wenn der Compiler memcpy() weg optimiert, dann ändert sich auch das 
alignment nicht. Außerdem sehe dann keinen Unterschied zum gecasteten 
Pointer, der letztendlich auch keine Code erzeugt.

von Peter II (Gast)


Lesenswert?

Stefan U. schrieb:
> Wenn der Compiler memcpy() weg optimiert, dann ändert sich auch das
> alignment nicht. Außerdem sehe dann keinen Unterschied zum gecasteten
> Pointer, der letztendlich auch keine Code erzeugt.

es gibt halt Tricks wie der Compiler 4 Byte ohne memcpy übertragen kann. 
Es werden aber immer noch 4 Byte an die Adresse vom float übertragen. 
Damit stimmt dann das alignment.

Wenn man hart ein int auf float castet, dann muss die Adresse vom int 
auch als float lesbar sein.

Auch mit dem cast werden 4 Byte umkopiert.

von Daniel A. (daniel-a)


Lesenswert?

Mampf F. schrieb:
> Die Lib unterstützt auch garnichts anderes außer einer Endian-Art und
> nur IEEE754.

IEEE 754 ist der standard, und convertier Funktionen zwischen Big und 
Little endian sind nun wirklich trivial, warum sollte ich denn 
irgendetwas anderes als IEEE 754 in Big Endian implementieren?

Little endian wird doch sowieso nur in einigen MS Formaten und 
Pseudostandards verwendet, und eventuell noch in einigen Freedesktop 
"Standards", und von denen halte ich nicht besonders viel. Die C 
standard liabrary hat auch kein Equivalent zu hton für little endian, 
bei all den MS Dateiformaten haben die Entwickler das doch direkt ohne 
Konvertierung rausgeschrieben, jedes MS Programm ist in der hinsicht 
garantiert kaputt Programiert, aber Windows läuft ja sowieso nur auf x86 
und amd64 CPUs.

> Und Buggy ist sie auch:
>
>> Subnormal floating point values (values really close to zero) are
>> truncated to zero for simplicity reasons. I may change this someday.

Nein, nicht buggy, nur etwas weniger genau für Zahlen mit 35 Nullen 
hinter dem Komma bei 32bit, oder 307 nullen hinter dem Komma für 64bit. 
Auf der Logarithmischen Scalala existierten die nummern garnicht mehr, 
also hat man sie linear verteilt, sinvoll gerundete Resultate in dem 
bereich hat man also keine.

Niemand rechnet absichtlich mit Subnormalen zahlen, einige CPU 
architekturen die IEEE 754 implementieren haben subnormale ebenfalls 
einfach ignoriert. Der einzige Zweck von Subnormalen war, dass bei 
Substraktionen von 2 Subnormalen nummern die Mathematisch nicht 0 
ergeben das Ergebnis wirklich nicht 0 ist, aber wegen Ungenauigkeiten 
bei Floats vergleicht diese sowieso niemand dierekt, auch nicht mit 0, 
statdessen verwenden bei float vergleichen alle einen Threshold für 
deren Delta, womit Subnormale wieder absolut sinnlos werden. Es gibt 
sogar Situationen in denen Subnormale Probleme machen.

Wenn dir die Subnormalen aber wirklich so wichtig sind, kannst du ja 
einfach die Librarie erweitern, und einen Pull request machen. Solange 
keine Hacks oder Annahmen zur Implementation der Floats auf 
Hardwareebene enthalten sind, nehme ich diese gerne an.

Grösste subnormalen:
http://www.binaryconvert.com/result_float.html?hexadecimal=007FFFFF
http://www.binaryconvert.com/result_double.html?hexadecimal=000FFFFFFFFFFFFF

Argumente gegen Subnormale:
https://en.m.wikipedia.org/wiki/Denormal_number#Performance_issues

von Stefan F. (Gast)


Lesenswert?

> es gibt halt Tricks wie der Compiler 4 Byte ohne memcpy übertragen kann.

Wie kopiert man denn 4 Bytes ohne Code?

von Stefan F. (Gast)


Lesenswert?

Ich verstehe gar nicht, warum ihr euch so über das float Format 
ereifert.
Ralfs Programm legt einen float Wert im Speicher ab, um ihn später 
wieder zu lesen. Er weiß, daß seine float Werte 4 Bytes groß sind.

Was hat das nun mit dem konkreten IEEE Format zu tun? Nichts! Sein 
Programm wird immer imstande sein, die float Werte zu lesen, die es 
vorher geschrieben hat. Ganz egal, wie sein Compiler oder die CPU das 
intern handhabt.

von Peter II (Gast)


Lesenswert?

Stefan U. schrieb:
> Wie kopiert man denn 4 Bytes ohne Code?

ich habe nicht geschrieben ohne code sondern ohne Funktionsaufruf.


Wenn man 4 Byte in einer float variable braucht muss immer kopiert 
werden!.

Beitrag #5111886 wurde von einem Moderator gelöscht.
von Peter II (Gast)


Lesenswert?

Arduino F. schrieb im Beitrag #5111886:
> Nöö...
>
> Die Daten, bei meiner Union Geschichte, werden komplett in den Registern
> gehalten, wenn man die Funktion inline macht.

willst du die ganze zeit die Variable in der Union behalten? Oder 
irgendwann mal in eine float variable? Spätestens dann wird kopiert.

wenn es nur als return verwendet wird, wird es auch mit memcpy auf das 
gleiche optimiert.

Wenn man es richtig macht muss man memcyp verwenden, alles andere sind 
Hacks die ihre Einschränkung haben.

von Mampf F. (mampf) Benutzerseite


Lesenswert?

Daniel A. schrieb:
> IEEE 754 ist der standard, und convertier Funktionen zwischen Big und
> Little endian sind nun wirklich trivial, warum sollte ich denn
> irgendetwas anderes als IEEE 754 in Big Endian implementieren?

und

Daniel A. schrieb:
> Eine CPU Architektur muss nicht zwingend IEEE 754 für floating point
> Operationen, verwenden, und ein float muss nicht zwingend 32bit gross
> sein.

und

Daniel A. schrieb:
> Auch bit und byte order können unterschiedlich sein. Solange man
> keine Daten zwischen unterschiedlichen Systemen austauscht wäre
> zumindest memcpy akzeptabel ... Wenn man jedoch zwischen verschiedenen
> Geräten Daten austauschen will,muss man sicherstellen, dass diese auf
> allen möglichen Plattformen
> identisch gelesen und geschrieben werden, und das ist wofür man diese
> Library brauchen kann.
> Ich versuche meinen Code immer so zu schreiben, dass er
> Programmunabhängig ist.

Wüsste nicht, wie deine Aussagen irgendwie zusammen passen ...

So oder so, deine Lösung ist nichts, was ich mir bookmarken werde, weil 
ich den Sinn dahinter nicht erkennen kann :)

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.