2015-10-05 112 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。 –