5

I'm looking for a robust and elegant way to extract four big-endian bytes from an array as a Float.

I can get a UInt32 with the bits via something like this:

let data: [Byte] = [0x00, 0x00, 0x00, 0x40, 0x86, 0x66, 0x66, 0x00]
let dataPtr = UnsafePointer<Byte>(data)
let byteOffset = 3
let bits = UnsafePointer<UInt32>(dataPtr + byteOffset)[0].bigEndian

But I can't figure out a good way to convert this into a Float in Swift.

For example, in Java:

float f = Float.intBitsToFloat(bits)

or in C:

float f = *(float *)&bits;

I tried casting the dataPtr to a float UnsafePointer, but then the endianness is a problem.

Any suggestions?

NickHowes
  • 133
  • 2
  • 14

3 Answers3

5

The floating point types have a static _fromBitPattern that will return a value. <Type>._BitsType is a type alias to the correctly sized unsigned integer:

let data: [Byte] = [0x00, 0x00, 0x00, 0x40, 0x86, 0x66, 0x66, 0x00]
let dataPtr = UnsafePointer<Byte>(data)
let byteOffset = 3
let bits = UnsafePointer<Float._BitsType>(dataPtr + byteOffset)[0].bigEndian
let f = Float._fromBitPattern(bits)

You don't see that method in auto-completion, but it's a part of the FloatingPointType protocol. There's an instance method that will give you back the bits, called ._toBitPattern().

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
Nate Cook
  • 92,417
  • 32
  • 217
  • 178
4

The equivalent Swift code is

let flt = unsafeBitCast(bits, Float.self)

which gives 4.2 with your data.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
0

Here's the solution for Swift 3:

Float(bitPattern: bits)
Hans Brende
  • 7,847
  • 4
  • 37
  • 44