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

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

    Hab 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 bei 1.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.
    🙂


Anmelden zum Antworten