Forum: Compiler & IDEs float-Rundungsfehler (INF) bei Verwendung der glibc sourcen


von Alec (Gast)


Lesenswert?

Hallo alle,

hoffe es sind einige mathe-cracks unter euch, bzw. jemand der gut mit 
floating point ist :)

Habe mir einige sourcen u.a. aus der glibc gezogen, beispielsweise:
powf(): http://ftp.gnu.org/gnu/glibc/glibc-2.9.tar.gz -> 
glibc-2.9/sysdeps/ieee754/flt-32/e_powf.c
und expf(): http://lxr.e2g.org/source/bionic/libm/src/e_expf.c

Wenn ich diese sourcen anstelle der Librarys direkt in meinen Code 
einbaue bekomme ich das Problem, das im Grenzbereich nicht korrekt 
gerundet wird, bzw. nicht auf +/-INF, ansonsten wir richtig gerechnet:

powf(100.0,100.0)    = 1.#INF00
my_powf(100.0,100.0) = 
1000000030094932700000000000000000000000000000000000000000000.000000

expf(100.000000)    = 1.#INF00
my_expf(100.000000) = 
1000000030094932700000000000000000000000000000000000000000000.000000

Kann mir jemand nen Tipp geben woran das liegt? Wo ist der Unterschied? 
IDE ist Eclipse + MinGW GCC unter XP, das ganze soll aber später auf ner 
embedded 32-bit CPU laufen.

Vielen Dank.
Alec

von Klaus W. (mfgkw)


Lesenswert?

Dein ausgegebener Dezimalwert sagt nichts aus, solange du nicht sagen
kannst, wie er zustande kommt.
Vielleicht ist es ja ein INF oder NAND, und du merkst es gar nicht?

Das berechntete Bitmuster würde mehr sagen.

von Alec (Gast)


Lesenswert?

Ausgabe erfolgt via printf("%f"). Habe auch schon gemerkt, das es daran 
liegt und nicht an der Berechnung in der Funktion. Denn binär sind die 
Ergebnisse identisch.
Wenn ich beide Funktionsergebnisse einer float-variablen zuweise und 
diese dann ausgebe, stimmt auch die ausgabe via printf().
Kann mir jemand erläutern warum?

f1=expf(f);      printf("   expf(%f) = %f [%X]\n",f,f1,*((int*)&f1));
f2=my_expf(f);   printf("my_expf(%f) = %f [%X]\n",f,f2,*((int*)&f2));
   expf(12345678.000000) = 1.#INF00 [7F800000]
my_expf(12345678.000000) = 1.#INF00 [7F800000]

printf("   expf(%f) = %f\n",f,expf(f));
printf("my_expf(%f) = %f\n",f,my_expf(f));
   expf(12345678.000000) = 1.#INF00
my_expf(12345678.000000) = 
1000000030094932700000000000000000000000000000000000000000000.000000

von Karl H. (kbuchegg)


Lesenswert?

Alec schrieb:

> Wenn ich beide Funktionsergebnisse einer float-variablen zuweise und
> diese dann ausgebe, stimmt auch die ausgabe via printf().
> Kann mir jemand erläutern warum?

Du hast weiter oben erwähnt, dass das ganze auf eine 32 Bit CPU soll.

Hast du dort echte double?

float != double

float hat wesentlich geringere Genauigkeit. Kein Wunder, hat ja auch 
weniger Bits zur Verfügung.

Speicherst du ein double Ergebnis, ehe es von einer Funktion die double 
erwartet weiterverarbeitet wird, zwischendurch in einer float Variablen 
ab, dann verlierst du dabei Bits.

von Klaus W. (mfgkw)


Lesenswert?

Alec schrieb:
> Wenn ich beide Funktionsergebnisse einer float-variablen zuweise und
> diese dann ausgebe, stimmt auch die ausgabe via printf().
> Kann mir jemand erläutern warum?

David Goldberg kann das:
http://www-users.math.umd.edu/~jkolesar/mait613/floating_point_math.pdf

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.
Lade...