2

The code which I am using for getting data in bytes, but I am not getting correct byte data for float value

let count = data.length / sizeof(UInt32)

// create array of appropriate length:
var array = [UInt32](count: count, repeatedValue: 0)

// copy bytes into array
data.getBytes(&array, length:count * sizeof(UInt32))

print(array)
Twitter khuong291
  • 11,328
  • 15
  • 80
  • 116
Nisha Nair
  • 327
  • 1
  • 5
  • 17
  • 2
    What exactly is the input data and what the expected result? The title says "convert a float value to byte array" and your code does "NSData to UInt32 array", so your problem is not clear to me :) – Martin R Apr 23 '16 at 15:22
  • Hi Thanks for the reply, if I am having float value, I want to convert that float value in bytes. so let me know what should I do for that? – Nisha Nair Apr 23 '16 at 15:27
  • Example please? Do you want the IEEE 754 representation or the `integer.fraction` representation in binary? – Code Different Apr 23 '16 at 15:39
  • Suppose for e.g float value is 40.0 , I want this float value to be converted in NSData, and then the reverse case also nsdata to float. – Nisha Nair Apr 23 '16 at 15:47

2 Answers2

6

Float to NSData:

var float1 : Float = 40.0
let data = NSData(bytes: &float1, length: sizeofValue(float1))
print(data) // <00002042>

... and back to Float:

var float2 : Float = 0
data.getBytes(&float2, length: sizeofValue(float2))
print(float2) // 40.0

(The same would work for other "simple" types like Double, Int, ...)

Update for Swift 3, using the new Data type:

var float1 : Float = 40.0
let data = Data(buffer: UnsafeBufferPointer(start: &float1, count: 1))
print(data as NSData) // <00002042>

let float2 = data.withUnsafeBytes { $0.pointee } as Float
print(float2) // 40.0

(See also round trip Swift number types to/from Data)

Update for Swift 4 and later:

var float1 : Float = 40.0
let data = Data(buffer: UnsafeBufferPointer(start: &float1, count: 1))

let float2 = data.withUnsafeBytes { $0.load(as: Float.self) } 
print(float2) // 40.0

Remark: load(as:) requires the data to be properly aligned, for Float that would be on a 4 byte boundary. See e.g. round trip Swift number types to/from Data for other solutions which work for arbitrarily aligned data.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • `Float(bitPattern: UInt32(bigEndian: data.withUnsafeBytes { $0.pointee } ))` whats different in this data to float conversion as it's outputting different value actually I need reverse of this means Float to Data but above code in your answer is not converting as expected, please help – Varun Naharia Oct 04 '17 at 12:49
  • Note that the Swift 3 version shown here now generates a warning with Swift 5: `Initialization of 'UnsafeBufferPointer' results in a dangling buffer pointer` – featherless Jun 21 '20 at 14:59
  • 1
    @featherless: I get a different warning “'withUnsafeBytes' is deprecated” and I have updated the code. It should now compile without warnings. – Martin R Jun 21 '20 at 15:19
  • Thanks for the update Martin. The new code does work + compile but it looks like it doesn't handle misaligned data. See https://github.com/jverkoey/BinaryCodable/pull/58/files for the fix I put in place based on swift-nio's number conversion implementation: https://github.com/apple/swift-nio/blob/06649bb8c704a042fc07f2013ae429e2d646e7bb/Sources/NIO/ByteBuffer-int.swift#L50-L61 – featherless Jul 05 '20 at 22:48
  • @featherless: That is correct, `load(as:)` requires the data to be properly aligned. (See also https://forums.swift.org/t/built-in-unaligned-loads/19664 in the Swift Forum.) For arbitrarily aligned data I wrote something here https://stackoverflow.com/a/38024025/1187415, that is essentially the same approach as in your link. – Martin R Jul 06 '20 at 05:32
6

Swift 5 Solution

From Float to [UInt8]

extension Float {
   var bytes: [UInt8] {
       withUnsafeBytes(of: self, Array.init)
   }
}

Usage:

let number: Float = 36.5
let bytes = number.bytes

From [UInt8] to Float

bytes.withUnsafeBytes {
    $0.load(fromByteOffset: 0, as: Float.self)
}

To convert to Data, simply cast the array of bytes to Data

let data = Data(bytes)
codingspark
  • 99
  • 1
  • 2