如何在Swift中将浮点数转换为字节数组?

3

我正在使用的代码用于获取以字节为单位的数据,但是对于浮点值,我没有得到正确的字节数据。

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)

2
输入数据是什么,期望的结果又是什么?标题说的是“将浮点数转换为字节数组”,而你的代码却是“NSData转换为UInt32数组”,所以我对你的问题不太清楚 :) - undefined
嗨,谢谢回复。如果我有一个浮点数值,我想将它转换为字节。请告诉我应该怎么做? - undefined
请问你要的是IEEE 754表示法,还是以二进制形式表示的“整数.小数”表示法的例子? - undefined
假设例如浮点值为40.0,我想将此浮点值转换为NSData,然后再将NSData转换回浮点数。 - undefined
2个回答

7

浮点数 转换为 NSData:

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

...返回到Float

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

对于其他“简单”类型,例如 DoubleInt 等,同样适用。

Swift 3更新:使用新的Data类型:

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

(另请参见往返于Swift数字类型和Data之间

更新Swift 4及更高版本:

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

备注: load(as:) 要求数据正确对齐,对于Float来说应该是在4字节边界上。请参阅往返转换Swift数值类型和Data了解其他适用于任意对齐数据的解决方案。


Float(bitPattern: UInt32(bigEndian: data.withUnsafeBytes { $0.pointee } )) 这段代码是将数据转换为浮点数。按照这种方式进行转换时,输出的值与预期不同。实际上,我需要相反的转换,即从浮点数转换为数据。请帮忙解决这个问题。 - undefined
请注意,这里显示的Swift 3版本现在在Swift 5中会生成一个警告:UnsafeBufferPointer<Self>的初始化导致悬空的缓冲指针 - undefined
1
@featherless: 我收到了一个不同的警告:“'withUnsafeBytes' 已被弃用”,并且我已经更新了代码。现在应该可以编译而没有警告了。 - undefined
感谢更新,马丁。新代码确实可以工作和编译,但似乎不能处理数据不对齐的情况。请参考我根据swift-nio的数字转换实现所做的修复:https://github.com/jverkoey/BinaryCodable/pull/58/files。具体实现可参考swift-nio的ByteBuffer-int.swift文件中的第50至61行:https://github.com/apple/swift-nio/blob/06649bb8c704a042fc07f2013ae429e2d646e7bb/Sources/NIO/ByteBuffer-int.swift#L50-L61。 - undefined
@featherless: 是的,load(as:) 需要数据正确对齐。(另请参阅 Swift 论坛中的 https://forums.swift.org/t/built-in-unaligned-loads/19664) 对于任意对齐的数据,我在这里写了一些内容 https://dev59.com/zFoT5IYBdhLWcg3w6i23#38024025,本质上与你提供的链接相同。 - undefined

6

Swift 5 解决方案

Float 转换为 [UInt8]

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

使用方法:

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

[UInt8]Float

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

要转换为数据,只需将字节数组强制转换为 Data

let data = Data(bytes)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接