2015-10-05 157 views
3

我希望能够从二进制文件中读取一半浮点数并将它们转换为Swift中的浮点数。我查看了其他语言(如Java和C#)的几次转换,但是我无法获得与半浮点数对应的正确值。如果任何人都可以帮我实施,我将不胜感激。从Float到Half Float的转换也是非常有用的。这是我试图从这个Java implementation转换的实现。在Swift中将半精度浮点数(字节)转换为浮点数

static func toFloat(value: UInt16) -> Float { 
    let value = Int32(value) 
    var mantissa = Int32(value) & 0x03ff 
    var exp: Int32 = Int32(value) & 0x7c00 
    if(exp == 0x7c00) { 
     exp = 0x3fc00 
    } else if exp != 0 { 
     exp += 0x1c000 
     if(mantissa == 0 && exp > 0x1c400) { 
      return Float((value & 0x8000) << 16 | exp << 13 | 0x3ff) 
     } 
    } else if mantissa != 0 { 
     exp = 0x1c400 
     repeat { 
      mantissa << 1 
      exp -= 0x400 

     } while ((mantissa & 0x400) == 0) 
     mantissa &= 0x3ff 
    } 
    return Float((value & 0x80000) << 16 | (exp | mantissa) << 13) 
} 
+0

类似的问题在这里:[如何将字节转换为Swift中的半浮点数?](http://stackoverflow.com/questions/32933771/how-to-convert-bytes-to-half-floats-in-swift ) –

回答

4

如果你有半精度数据的数组,你可以将所有的它立刻使用vImageConvert_Planar16FtoPlanarF,这是由Accelerate.framework提供浮动:

import Accelerate 
let n = 2 
var input: [UInt16] = [ 0x3c00, 0xbc00 ] 
var output = [Float](count: n, repeatedValue: 0) 
var src = vImage_Buffer(data:&input, height:1, width:UInt(n), rowBytes:2*n) 
var dst = vImage_Buffer(data:&output, height:1, width:UInt(n), rowBytes:4*n) 
vImageConvert_Planar16FtoPlanarF(&src, &dst, 0) 
// output now contains [1.0, -1.0] 

您还可以使用这种方法来转换个人价值观,但如果这就是你所做的一切,那么它就相当重量级;另一方面,如果你有大的缓冲区值进行转换,它是非常有效的。

如果你需要转换隔离值,可以把类似下面的C函数在你的桥接报头,并使用它从斯威夫特:

#include <stdint.h> 
static inline float loadFromF16(const uint16_t *pointer) { return *(const __fp16 *)pointer; } 

这将使用当你编译硬件转换指令具有它们的目标(armv7s,arm64,x86_64h),并且在编译没有硬件支持的目标时调用合理的软件转换例程。

编:去你可以浮动转换为半精度在几乎相同的方式的其他方式

static inline storeAsF16(float value, uint16_t *pointer) { *(const __fp16 *)pointer = value; } 

或者使用功能vImageConvert_PlanarFtoPlanar16F

+0

非常感谢。比我预想的要简单。是否有类似于从浮动到半浮动的另一种方式? – Benny33

+0

@ Benny33:更新了我的答案,指示F - > 16F。 –