float - Operation liefert merkwürdige Ergebnisse
-
im 3.fall handelt es sich offensichtlich um einen double datentyp, dies erklärt alles. wie man da irgendwas von registern faseln kann ist mir völlig schleierhaft...
-
.file "test.c" .def ___main; .scl 2; .type 32; .endef .section .rdata,"dr" LC2: .ascii "x+y : %30.15f\12\0" LC3: .ascii "(float)(x+y): %30.15f\12\0" LC4: .ascii "1.0f + 1E-9f: %30.15f\12\0" .text .p2align 4,,15 .globl _main .def _main; .scl 2; .type 32; .endef _main: pushl %ebp movl $16, %eax movl %esp, %ebp subl $24, %esp andl $-16, %esp call __alloca call ___main movl $LC2, (%esp) movl $0x3089705f, %eax movl $0x3f800000, %edx movl %eax, -8(%ebp) movl %edx, -4(%ebp) flds -8(%ebp) fadds -4(%ebp) fstpl 4(%esp) call _printf flds -8(%ebp) fadds -4(%ebp) movl $LC3, (%esp) fstpl 4(%esp) call _printf movl $LC4, (%esp) fld1 fstpl 4(%esp) call _printf leave xorl %eax, %eax ret .def _printf; .scl 3; .type 32; .endef
kompiliert: gcc test.c -O3 -ffloat-store -S
-
Bajou schrieb:
im 3.fall handelt es sich offensichtlich um einen double datentyp, dies erklärt alles. wie man da irgendwas von registern faseln kann ist mir völlig schleierhaft...
Das einzige was hier offensichtlich ist: Du hast keine Ahnung bzw. du bist ein Troll. Aber du kannst mir mal 2 Dinge erklären:
- Warum hat der OP im 3. Fall trotz des deiner Meinung nach genaueren doule-Typs eine ungenaueres Ergebnis?
- Warum sollte der Ausdruck im 3. Fall den Typ double haben?@ feraL: Nett gemeint, aber eigentlich wollte ich das vom OP. Und dann am besten einmal ohne Optimierung, einmal mit O3 und einmal mit -ffloat-store und O3. Natürlich auch den Textoutput mit angeben.
-
Also in allen 3 Fällen werden 2 Float-Größen addiert.
Im ersten und 2. Fall ist das Ergebnis dieser Addition wohl vom Typ double,
erkennbar für mich am genaueren Ergebnis.
Die Addition der beiden Float-Konstanten im 3. Fall liefert ein Ergebnis vom Typ float wegen des ungenaueren Ergebnisses.Gibts da keine allgemeine Regel, wie mit 2 float-Operanden bei einer arithmetischen Operation verfahren wird? Hab was gelesen, dass in ANSI-C arithmetische Operationen in double vorgenommen werden, dann passt aber das 3. Ergebnis nicht.
Rätselhaft ....
-
Tim, Du hast recht!
Beim Übersetzen mit
gcc -O3 oder gcc -ffloat-store sind alle 3 Ergebnisse identisch:x+y : 1.000000000000000
(float)(x+y): 1.000000000000000
1.0f + 1E-9f: 1.000000000000000Hab wohl vorher irgendwas falsch gemacht, bitte um Entschuldigung.
Fazit: die Regel heisst also:
Bei Operanden vom Typ float ist das Ergebniss auch vom Typ float.Ggf. kann durch Registeroperationen eine höhere Genauigkeit erreicht werden, wenn das System das hergibt, wie Du in Deiner ersten Antwort geschrieben hast.
Vielen Dank für Deine Hilfe!
Gruß
peule
-
peule schrieb:
Fazit: die Regel heisst also:
Bei Operanden vom Typ float ist das Ergebniss auch vom Typ float.naja, compiler machen manchmal 'promotions' und 'arthmetic conversions' um die genauigkeit von berechnungen zu verbessern. wann sowas zuschlägt steht irgendwo im c-standard. jedenfalls würde ich nicht davon ausgehen, dass (float)a+float(b) das selbe ist wie (float)(a+b).
-
Sind a und b bei dir denn auch floats? Such mir bitte mal die Stelle im Standard raus. Ich finde sie nicht.
-
Tim schrieb:
Such mir bitte mal die Stelle im Standard raus. Ich finde sie nicht.
wenn du's nicht findest, dann hab' ich mich wohl getäuscht. floats und doubles traue ich trotzdem nicht über'n weg.
-
~fricky schrieb:
Tim schrieb:
Such mir bitte mal die Stelle im Standard raus. Ich finde sie nicht.
wenn du's nicht findest, dann hab' ich mich wohl getäuscht.
Es gibt die "usual arithmetic conversions". Die sagen z.B. dass bei
1.0 + 1.0f
der float-Operand nach double gewandelt wird, aber bei1.0f + 1.0f
findet nichts mehr statt.~fricky schrieb:
floats und doubles traue ich trotzdem nicht über'n weg.
Ja, aber sie machen das Leben manchmal deutlich einfacher.
-
Tim schrieb:
~fricky schrieb:
floats und doubles traue ich trotzdem nicht über'n weg.
Ja, aber sie machen das Leben manchmal deutlich einfacher.
nunja, für numerisch/mathematische anwendungen, wobei man die feine auflösung braucht, sind sie gut. trotzdem muss man sich mit rundungsfehlern rumplagen. und wenn floats emuliert werden, ist's zudem noch langsam. für die meisten fälle ist doch die mod 2^registerbreiten-arithmetik (integer) einfach besser.