Addition + Rundung



  • Hallo,

    ich möchte zwei Double-Zahlen addieren mit Rundung nach oben.

    pushl %ebp
    movl %esp, %ebp
    fnstcw -16(%ebp)
    fnstcw -8(%ebp)
    orw $0x0800, -8(%ebp)
    fldcw -8(%ebp)
    fldl 8(%ebp)
    faddl 16(%ebp)
    fldcw -16(%ebp)
    movl %ebp, %esp
    popl %ebp

    Aber er rundet nicht nach oben. Wo liegt denn der Fehler?

    Gruß

    Boris



  • Ok, ich habe den Fehler gefunden, er liegt in folgender Zeile:
    fldcw -16(%ebp)
    Nur sehe ich den Fehler nicht. So bald ich diese Zeile ausführen lassen,
    ist das Ergebnis falsch, aber warum???


  • Mod

    es finden zwei rundungen statt - die erste bei der addition. die zweite dann wenn das ergebnis dann in einem double gespeichert wird - das findet aber erst nach dem assembler teil statt - wenn das controlwort zurückgestzt wurde.
    eine lösung ist, auf das rücksetzen zu verzichten - zum setzen des controlworts muss man ohnehin keinen assembler bemühen. die andere ist, die umwandlung in ein double durch ein fstp/fld paar zu forcieren (bevor das controlwort zurückgesetzt wird) - das kostet nicht übermässig viel zeit, ist im grunde dasselbe, was -ffloat-store auch tut.
    nebenbei bemerkt, ist das lokale ändern des controlworts auf etwas anderes als round_nearest oder chop extrem unperformant (generell umschalten zwischen mehr als 2 verschiedenen werten, und diese beiden sind diejenigen, die der compiler sowieso benutzt, einmal fürs normale rechnen, das andere wenn in ints gewandelt wird). rechne mit ~150takten/fldcw auf einem P4. beim athlon ist es auch nicht viel besser.


Anmelden zum Antworten