2015-04-11 18 views
5

Wie kann ich die raw-Bytes von Float oder Double in Swift lesen?Erhalten rohe Bytes eines Schwimmers in Swift

Beispiel:

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

Ich möchte bytes1 und bytes2 den gleichen Wert enthalten, da diese binäre Zahl der Float Darstellung 1.5 ist.

Ich brauche es zu bitweisen Operationen wie & und >> zu tun (diese sind nicht auf einem Float definiert).

Antwort

10

Update für Swift 3: Ab Swift 3, alle Gleitkommatypen bitPattern Eigenschaft haben, die mit den gleichen Speicher Darstellung eine unsignierte ganze Zahl zurückgibt, und eine entsprechende init(bitPattern:) Konstruktor für die entgegengesetzte Umwandlung.

Beispiel:Float zu UInt32:

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

Beispiel:UInt32 zu Float:

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

Auf die gleiche Weise können Sie zwischen Double und UInt64, oder zwischen CGFloat konvertieren ein nd UInt.


Alte Antwort für Swift 1.2 und Swift 2: Die Swift Gleitkomma-Typen haben eine _toBitPattern() Methode:

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 

Diese Methode Teil des FloatingPointType Protokoll ist zu dem Float, Double und CGFloat entsprechen:

/// 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 

    // ... 
} 

(Ab Swift 2 sind diese Definitionen in der API-Dokumentation nicht mehr sichtbar, aber sie sind weiterhin vorhanden und funktionieren wie zuvor.)

Die tatsächliche Definition von _BitsType ist in der API Dokumentation nicht sichtbar, aber es ist UInt32 für Float, UInt64 für Double und Int für 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() kann für die Umwandlung verwendet werden, in die andere Richtung:

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

Leider ist diese Lösung nicht für Swift funktioniert 2.1 – Qbyte

+0

@Qbyte: Ich habe den Code mit Xcode 7.1.1 und 7.2 beta 3 überprüft. Abgesehen von der notwendigen Änderung "println" -> "print" alles kompiliert und funktioniert wie erwartet. - Welchen Fehler bekommst du? Welche Xcode-Version verwenden Sie? –

+0

Das ist seltsam ... es funktioniert jetzt. Der Auszug des 'FloatingPointType'-Protokolls, insbesondere' func _toBitPattern() ', kann jedoch nicht gefunden werden. – Qbyte

3

Sie können unsafeBitCast wie folgt verwenden:

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

Die oben druckt "Success" wenn Sie es ausführen.

0

konnte nicht bekommen dies funktioniert:

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

oder dies:

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

So ging ich dies für:

print(String(x.bitPattern, radix: 2)) 
Verwandte Themen