Get raw bytes of a float in Swift

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-04 06:01:04

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.

Could not get this to work:

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

or this:

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

So I went for this:

print(String(x.bitPattern, radix: 2))
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!