Typwandlung zur Übersetzungszeit?

22/07/2011 - 10:41 von Georg Bauhaus | Report spam
Moin,

Gegeben

float foo(float f)
{
return f / 123.45;
}

Also nicht f / 123.45f. Darf ein compiler den Literal
123.45 in 123.45f quasi wandeln und entsprechend (weniger)
Anweisungen erzeugen?
 

Lesen sie die antworten

#1 Markus Wichmann
22/07/2011 - 11:29 | Warnen spam
On 22.07.2011 10:41, Georg Bauhaus wrote:
Moin,

Gegeben

float foo(float f)
{
return f / 123.45;
}

Also nicht f / 123.45f. Darf ein compiler den Literal
123.45 in 123.45f quasi wandeln und entsprechend (weniger)
Anweisungen erzeugen?



Hmmm... Ich denke nicht, da die Ergebnisse sich unterscheiden können
(wegen der Genauigkeit könnten sich die letzten paar Bit àndern).
Hàttest du als Konstante 123.5 gewàhlt, sodass sich float- und
double-Konstante nur durch die Anzahl nachfolgender Nullen
unterscheiden, dann vielleicht. Und tatsàchlich, der gcc macht das. Mit
der 123.45 generiert er:

cvtss2sd %xmm0, %xmm0 //mach aus f ein double
divsd .LC0(%rip), %xmm0 //dividiere die Konstante,
//die übrigens als double gespeichert ist
cvtsd2ss %xmm0, %xmm0 //mach das Ergebnis wieder zu float
ret //fertig

Mit 123.5:

divss .LC0(%rip) //dividiere die Konstante
//die übrigens als float gespeichert ist.
ret //fertig

Das heißt, was du vorschlàgst geht, wenn die Konstante einen
abbrechenden Binàrbruch hat. Ob sie das hat, ist nicht so leicht zu
klàren. Als Heuristik: Nimm nur den Nachkommateil. Zieh die größte
Zweierpotenz ab, die kleiner ist als der Teil.

Ist das Ergebnis 0? Wenn ja, ist die Zahl binàr exakt darstellbar.

Ist das Ergebnis ein Vielfaches einer negativen Zehnerpotenz? Wenn ja,
ist die Zahl nicht binàr exakt darstellbar.

Ansonsten machst du jetzt weiter mit der Subtraktion der größten
Zweierpotenz kleiner als das Ergebnis.

Beispiel: 123.45
0.45 - 0.25 = 0.2

0.2 = 2 * 1/10 -> nicht darstellbar

Ciao,
Markus

Ähnliche fragen