2016-07-08 26 views
3

ich eine Funktion getNthFloat(uint32 n) float32 so dass für jeden n will, m < 2³²-4 mit n ≠ m, getNthFloat(n) und getNthFloat(m) return verschiedener Schwimmer, dass reelle Zahlen (weder NaN oder ± ∞). 2³²-4 wird gewählt, denn wenn ich IEEE 754 richtig verstehe, gibt es zwei binäre Darstellungen von NaN, eine für ∞ und eine für -∞.generieren n verschiedene Schwimmern, die nicht ∞ oder NaN (in Go) sind

Ich stelle mir vor, ich sollte meine Uint32 in Bits konvertieren und Bits in Float32 konvertieren, aber ich kann nicht herausfinden, wie die vier Werte effizient vermieden werden.

Antwort

7

Sie erhalten nicht mehr als 2^32-4 gültig Gleitkommazahlen in einem float32. IEEE 754 binary32-Nummern haben zwei Unendlichkeiten (negativ und positiv) und 2^24-2 mögliche NaN-Werte.

Ein 32-Bit-Gleitkommazahl hat die folgenden Bits:

31 30...23 22...0 
sign exponent mantissa 

Alle Exponenten mit dem Wert 0xFF sind entweder unendlich (wenn Mantisse ist 0) oder NaN (wenn Mantisse nicht 0). Sie können diese Exponenten also nicht generieren.

Dann ist es nur eine einfache Sache oder Mapping Ihre zulässigen Ganzzahlen in diesem Format und dann math.Float32frombits verwenden, um eine float32 zu generieren. Wie du das machst, ist deine Entscheidung. Ich würde wahrscheinlich faul sein und nur das niedrigste Bit für das Zeichen verwenden und dann alle Zahlen höher als 2^32 - 2^24 - 1 ablehnen und dann die Bits verschieben.

So etwas wie dieses (nicht getestet):

func foo(n uint32) float32 { 
    if n >= 0xff000000 { 
     panic("xxx") 
    } 
    return math.Float32frombits((n & 1) << 31 | (n >> 1)) 
} 

N. B. Wahrscheinlich würde ich auch denormal Zahlen vermeiden, also Zahlen mit dem Exponenten 0 und der Mantisse ungleich Null. Sie können langsam sein und werden möglicherweise nicht korrekt behandelt. Zum Beispiel könnten sie alle auf Null abgebildet werden, es gibt nichts in der Go-Spezifikation, das darüber spricht, wie mit denormalsten Zahlen umgegangen wird, also würde ich vorsichtig sein.

+0

Haa, ich wusste nicht, dass es mehr als zwei binäre Darstellungen für NaN gibt, aber Sie haben Recht: https://play.golang.org/p/SIGEOULoFp druckt "nans: 16777213, infs: 2". Ich testete eine Anpassung Ihrer Lösung (um unnormale Zahlen zu vermeiden) und es funktioniert: https://play.golang.org/p/BPAyA0Ayo0. Vielen Dank! – Ted

+0

@Ted: Das ist seltsam. Es sollte '16777214' nans sein, nicht' 16777213'. (Selbst wenn es nicht offensichtlich ist, wie man sie zählt, ist es trivialerweise, dass NaN paarweise kommen, weil das "Vorzeichenbit" eines NaN ein anderes NaN gibt.) –

+1

@Ted: Ah, ich verstehe. Ihr 'b