How can I read the raw bytes of a Float or Double in Swift?
Example:
let x = Float(1.5)
let bytes1: UInt32 = getRawBytes(x)
let bytes2: UInt32 = 0b00111111110000000000000000000000
I want bytes1 and bytes2 to contain the same value, since this binary number is the Float representation of 1.5.
I need it to do bit-wise operations like & and >> (these are not defined on a float).
Update for Swift 3: As of Swift 3, all floating point types
have bitPattern property which returns an unsigned integer with
the same memory representation, and a corresponding init(bitPattern:)
constructor for the opposite conversion.
Example: Float to UInt32:
let x = Float(1.5)
let bytes1 = x.bitPattern
print(String(format: "%#08x", bytes1)) // 0x3fc00000
Example: UInt32 to Float:
let bytes2 = UInt32(0x3fc00000)
let y = Float(bitPattern: bytes2)
print(y) // 1.5
In the same way you can convert between Double and UInt64,
or between CGFloat and UInt.
Old answer for Swift 1.2 and Swift 2: The Swift floating point types have a _toBitPattern() method:
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
This method is part of the FloatingPointType protocol
to which Float, Double and CGFloat conform:
/// 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
// ...
}
(As of Swift 2, these definition are not visible anymore in the API documentation, but they still exist and work as before.)
The actual definition of _BitsType is not visible in the API
documentation, but it is UInt32 for Float, UInt64 for
Double, and Int for 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() can be used for the conversion into the other
direction:
let y = Float._fromBitPattern(0x3fc00000)
print(y) // 1.5
You can use unsafeBitCast, like this:
let x = Float(1.5)
let bytes1: UInt32 = unsafeBitCast(x, UInt32.self)
let bytes2: UInt32 = 0b00111111110000000000000000000000
if (bytes1 == bytes2) {
println ("Success")
}
The above prints "Success" when you run it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With