英文:
Swift Converting Data to double give me wrong value
问题
I have a Data with a list of bytes:
[64, 69, 207, 65, 61, 225, 199, 151]
hex string is equals: 4045cf413de1c797
I'm getting bytes with this function:
var bytes: [UInt64] = data.map { UInt64(bitPattern: Int64($0)) }
data is a Data type
when i convert it to a double i'm getting wrong value
I tried several function to convert it:
Example 1:
extension Data {
enum Endianess {
case little
case big
}
func toFloat(endianess: Endianess = .little) -> Float? {
guard self.count <= 4 else { return nil }
switch endianess {
case .big:
let data = [UInt8](repeating: 0x00, count: 4-self.count) + self
return data.withUnsafeBytes { $0.load(as: Float.self) }
case .little:
let data = self + [UInt8](repeating: 0x00, count: 4-self.count)
return data.reversed().withUnsafeBytes { $0.load(as: Float.self) }
}
}
}
This one gives me Nil
Example 2:
var f: Float = 0.0
memcpy(&f, bytes, 4)
The result: 8.96831017167883e-44
Example 3:
let floatNb: Float = dataSliced.reversed().withUnsafeBytes { $0.load(as:
Float.self)
}
The result: 0.11024397
without reversed() i'm getting error:
Fatal error: load from misaligned raw pointer
Example 4:
extension Numeric {
init<D: DataProtocol>(_ data: D) {
var value: Self = .zero
let size = withUnsafeMutableBytes(of: &value, { data.copyBytes(to: $0)} )
//assert(size == MemoryLayout.size(ofValue: value))
self = value
}
}
Result is: -4.089067083288947e-194
The good result is: 43.61917851948163
How can i convert properly a Data to double?
Any help will be appreciated
英文:
I have a Data with a list of bytes :
[64, 69, 207, 65, 61, 225, 199, 151]
hex string is equals : 4045cf413de1c797
I'm getting bytes with this function :
var bytes: [UInt64] = data.map { UInt64(bitPattern: Int64($0)) }
data is a Data type
when i convert it to a double i'm getting wrong value
I tried several function to convert it :
Example 1 :
extension Data {
enum Endianess {
case little
case big
}
func toFloat(endianess: Endianess = .little) -> Float? {
guard self.count <= 4 else { return nil }
switch endianess {
case .big:
let data = [UInt8](repeating: 0x00, count: 4-self.count) + self
return data.withUnsafeBytes { $0.load(as: Float.self) }
case .little:
let data = self + [UInt8](repeating: 0x00, count: 4-self.count)
return data.reversed().withUnsafeBytes { $0.load(as: Float.self) }
}
}
}
This one gives me Nil
Example 2 :
var f:Float = 0.0
memcpy(&f, bytes, 4)
The result : 8.96831017167883e-44
Example 3:
let floatNb:Float = dataSliced.reversed().withUnsafeBytes { $0.load(as:
Float.self)
}
The result : 0.11024397
without reversed() i'm getting error :
Fatal error: load from misaligned raw pointer
Example 4 :
extension Numeric {
init<D: DataProtocol>(_ data: D) {
var value: Self = .zero
let size = withUnsafeMutableBytes(of: &value, { data.copyBytes(to: $0)} )
//assert(size == MemoryLayout.size(ofValue: value))
self = value
}
}
Result is : -4.089067083288947e-194
The good result is : 43.61917851948163
How can i convert properly a Data to double ?
Any help will be appreciated
答案1
得分: 1
你的问题是,目标类型使用了 Float
而不是 Double
。Float
只使用前 4 个字节。
let bytes = [UInt8](arrayLiteral: 64, 69, 207, 65, 61, 225, 199, 151)
let result = bytes.reversed().withUnsafeBytes {
$0.load(
as: Double.self
)
}
assert(43.61917851948163 == result, "无效的结果 \(result)")
英文:
Your problem that as destination you are using Float
instead of Double
. Float
is using only first 4 bytes.
let bytes = [UInt8](arrayLiteral: 64, 69, 207, 65, 61, 225, 199, 151)
let result = bytes.reversed().withUnsafeBytes {
$0.load(
as:Double.self
)
}
assert(43.61917851948163 == result, "invalid result \(result)")
答案2
得分: 0
Here is the translated code:
最终,我通过这样分离 Int 和 Double 来使它工作了:
对于 Double:
let bytes: [UInt16] = dataSliced.map { UInt16(bitPattern: Int16($0)) }
dump(bytes)
if(bytes.count == 8){
var hexValue = dataSliced.toHex()
hexValue = "0x\(hexValue)"
let scanner = Scanner(string: hexValue)
var decimalValue: UInt64 = 0
scanner.scanHexInt64(&decimalValue)
doubleValue = Double(bitPattern: decimalValue)
print("doubleValue \(doubleValue)")
}
对于 Int:
let decimalValue = dataSliced.reduce(0) { value, byte in
return value << 8 | Int(byte)
}
return decimalValue
Please note that the code has been translated as requested, and I have removed any non-code content.
英文:
I finally get this worked by separating Int and Double like this :
For double :
let bytes: [UInt16] = dataSliced.map { UInt16(bitPattern: Int16($0)) }
dump(bytes)
if(bytes.count == 8){
var hexValue = dataSliced.toHex()
hexValue = "0x\(hexValue)"
let scanner = Scanner(string: hexValue)
var decimalValue: UInt64 = 0
scanner.scanHexInt64(&decimalValue)
doubleValue = Double(bitPattern: decimalValue)
print("doubleValue \(doubleValue)")
For Int
let decimalValue = dataSliced.reduce(0) { value, byte in
return value << 8 | Int(byte)
}
return decimalValue
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论