swiftdoublebytefloating

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


Solution

  • 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