mikrocontroller.net

Forum: Compiler & IDEs Negierung von float Wert


Autor: Pete (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich benutze einen float Wert in AVR-gcc.

float x = 27.1285.

Funktioniert perfekt in der Verbindung mit sprintf....

Jetzt möchte ich den Wert negieren ? (-27.1285)
Aus der Doku weiss ich das mein float 32bit, also 4 byte gross ist.

Muss ich jetzt das oberste Bit einfach auf 1 setzen ?
das könnte ich ja mit:

x |= 0x8000;

Vielen Dank schon mal für einen Hinweis.

Gruß Pete

: Gesperrt durch Moderator
Autor: Peter (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
float x = 27.1285.


x = 0 - x;

oder

x = d * -1;

alles andere ist nicht wirklich Portable.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter schrieb:
> float x = 27.1285.
>
>
> x = 0 - x;
>
> oder
>
> x = d * -1;
>
> alles andere ist nicht wirklich Portable.

Was ist denn an
x = -x;
nicht portabel?

Autor: Klaus (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Oder  x *= -1;

Oder, oder, oder... :)

Autor: yalu (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Stefan Ernst schrieb:

> Was ist denn an
>
> x = -x;
>
> nicht portabel?

Manchmal liegt das Naheliegende so fern (nämlich einfach ein
Minuszeichen vor die Variable zu schreiben) ;-)

Wer's undurchschaubar mag, kann natürlich auch
x = 1/(tan(atan(x)+M_PI/2))

schreiben. Das geht für fast alle x und stimmt wenigstens ungefähr ;-)

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, es geht aber auch

x = e^(-i * pi + ln(x))

Müsste man nur noch die ganzen Funktionen aus der Mathe Bibliothek 
zusammensammeln ;)

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
2 lesenswert
nicht lesenswert
> Aus der Doku weiss ich das mein float 32bit, also 4 byte gross ist.
> x |= 0x8000;
Damit würdest du z.B. das 15. Bit deiner 32-Bit-Zahl setzen...  :-o

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Lothar Miller schrieb:

> Damit würdest du z.B. das 15. Bit deiner 32-Bit-Zahl setzen...  :-o

Noch schlimmer.  Er würde die Gleitkommazahl in eine Ganzzahl
umwandeln und deren 15. Bit setzen.

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier wäre noch die Variante für die, die es in C schreiben wollen,
sich dabei aber auf die Zahlendarstellungsebene hinunter begeben
wollen. ;-)
double minus_x(double x)
{
        union {
                double x;
                unsigned char y[4];
        } u;

        u.x = x;
        u.y[3] -= 0x80;

        return u.x;
}

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da solltest du aber noch eine automatische Byteordererkennung anfügen.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:

> Da solltest du aber noch eine automatische Byteordererkennung anfügen.

Ich bin mir nicht einmal ganz sicher, ob der Algorithmus für
64-Bit-IEEE-854 der gleiche wäre.  Dort ist der Exponent ja
größer.

Gilt so erst einmal nur für 32-bit-FP auf little-endian (AVR).

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Exponent ist egal, weil das Vorzeichen in alle IEEE Formaten im 
höchsten Bit liegt. Aber die Byte-Order ist weniger einfach, wenn man 
auch jene schrägen Varianten berücksichtigt, in denen zwar das untere 
Byte aber das obere Wort vorneweg kommt.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Der Exponent ist egal, weil das Vorzeichen in alle IEEE Formaten im
> höchsten Bit liegt.

Ja, stimmt.

> Aber die Byte-Order ist weniger einfach,

Normalerweise gibt's das als Makro in einem Headerfile, aber das
ist dann halt gerade bei AVR & Co nicht da.

> wenn man
> auch jene schrägen Varianten berücksichtigt, in denen zwar das untere
> Byte aber das obere Wort vorneweg kommt.
#if BYTE_ORDER == PDP_ENDIAN

:)

Ich glaube, das hat dieser Tage nur noch historische Relevanz.

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oder noch etwas umständlicher:
float a = -2.1;
void *ptr;
ptr = memset(ptr+3, 0x40 , 1);

Autor: MaWin. (nur echt mit Punkt) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus schrieb:
> Oder noch etwas umständlicher:

Was natürlich nicht funktioniert.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich denke mal, der Compiler wird am besten wissen, wie man x = -x; 
optimiert.
Bei float irgendwelche kryptische, unlesbare und nicht portable 
Mikrooptimierungen hinzuschreiben, ist Blödsinn.

Autor: eagle user (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Jörg W. schrieb:
> A. K. schrieb:

>> wenn man
>> auch jene schrägen Varianten berücksichtigt, in denen zwar das untere
>> Byte aber das obere Wort vorneweg kommt.
>
>
#if BYTE_ORDER == PDP_ENDIAN
>
> :)
>
> Ich glaube, das hat dieser Tage nur noch historische Relevanz.

Aber nur, weil man eine PDP-11 lieber in Assembler programmiert :)

http://www.theregister.co.uk/2013/06/19/nuke_plant...

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und was ist am o.g. portablen, offensichtlichen, der mathematischen 
Notation folgenden, nicht kürzer formulierbaren, optimalen Code 
erzeugenden
 
float neg (float x)
{
    return -x;
}

auszusetzen?

Macht avr-gcc zu
 
neg:
  subi r25,0x80
  ret

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
2 lesenswert
nicht lesenswert
Klaus schrieb:
> Oder noch etwas umständlicher:

Und Du brauchtest sieben Jahre, um das herauszufinden?

Dieser Beitrag ist gesperrt und kann nicht beantwortet werden.