2015-04-11 10 views
5

Come posso leggere i byte non elaborati di uno Float o Double in Swift?Ottieni i byte grezzi di un float in Swift

Esempio:

let x = Float(1.5) 
let bytes1: UInt32 = getRawBytes(x) 
let bytes2: UInt32 = 0b00111111110000000000000000000000 

voglio bytes1 e bytes2 per contenere lo stesso valore, dal momento che questo numero binario è la rappresentazione di Float 1.5.

Ho bisogno di operazioni bit-like come & e >> (queste non sono definite su un float).

risposta

10

Aggiornamento per Swift 3: Al Swift 3, tutti i tipi a virgola mobile hanno bitPattern proprietà che restituisce un intero senza segno con la stessa rappresentazione memoria, e un corrispondente init(bitPattern:) costruttore per la conversione opposta.

Esempio:Float a UInt32:

let x = Float(1.5) 
let bytes1 = x.bitPattern 
print(String(format: "%#08x", bytes1)) // 0x3fc00000 

Esempio:UInt32 a Float:

let bytes2 = UInt32(0x3fc00000) 
let y = Float(bitPattern: bytes2) 
print(y) // 1.5 

Allo stesso modo è possibile convertire tra Double e UInt64, o tra CGFloat un nd UInt.


Old risposta per Swift 1.2 e Swift 2: I tipi virgola mobile Swift hanno un metodo _toBitPattern():

let x = Float(1.5) 
let bytes1 = x._toBitPattern() 
print(String(format: "%#08x", bytes1)) // 0x3fc00000 

let bytes2: UInt32 = 0b00111111110000000000000000000000 
print(String(format: "%#08x", bytes2)) // 0x3fc00000 

print(bytes1 == bytes2) // true 

Questo metodo fa parte della FloatingPointType protocollo cui Float, Double e CGFloat conforme:

/// A set of common requirements for Swift's floating point types. 
protocol FloatingPointType : Strideable { 
    typealias _BitsType 
    static func _fromBitPattern(bits: _BitsType) -> Self 
    func _toBitPattern() -> _BitsType 

    // ... 
} 

(A partire da Swift 2, queste definizioni non sono più visibili nella documentazione dell'API , ma esistono ancora e funzionano come prima.)

La definizione stessa di _BitsType non è visibile nella documentazione API , ma è UInt32 per Float, UInt64 per Double e Int per CGFloat:

print(Float(1.0)._toBitPattern().dynamicType) 
// Swift.UInt32 

print(Double(1.0)._toBitPattern().dynamicType) 
// Swift.UInt64 

print(CGFloat(1.0)._toBitPattern().dynamicType) 
// Swift.UInt 

_fromBitPattern() può essere utilizzato per la conversione nell'altro direzione:

let y = Float._fromBitPattern(0x3fc00000) 
print(y) // 1.5 
+0

Purtroppo questa soluzione non funziona per Swift 2.1 – Qbyte

+0

@Qbyte: Ho ricontrollato il codice con Xcode 7.1.1 e 7.2 beta 3. A parte il necessario cambiamento "println" -> "print" , tutto ha compilato e funzionato come previsto. - Che errore ottieni? Quale versione di Xcode stai usando? –

+0

È strano ... funziona ora. Ma non riesco a trovare l'estratto del protocollo 'FloatingPointType', in particolare' func _toBitPattern() '. – Qbyte

3

È possibile utilizzare unsafeBitCast, in questo modo:

let x = Float(1.5) 
let bytes1: UInt32 = unsafeBitCast(x, UInt32.self) 
let bytes2: UInt32 = 0b00111111110000000000000000000000 
if (bytes1 == bytes2) { 
    println ("Success") 
} 

Le stampe sopra "Success" quando lo si esegue.

0

Impossibile ottenere questo lavoro:

let x = Float(1.5) 
let bytes1 = x.bitPattern 
print(String(format: "%#08x", bytes1)) // 0x3fc00000 

o questo:

let bytes1: UInt32 = unsafeBitCast(x, UInt32.self) 

così sono andato a questo:

print(String(x.bitPattern, radix: 2)) 
Problemi correlati