如何将uint16转换为float16?Python内存缓冲区读取场景
uint16转float16的Python实现方案
高效批量转换(推荐用numpy)
从ctypes读取的uint16列表无法直接用astype(np.float16)转换,是因为astype做的是数值转换,而我们需要的是二进制位的直接解析——float16的二进制存储格式刚好和uint16的位结构完全对应,所以用numpy的view方法就能直接完成转换:
import numpy as np # 示例:从ctypes读取的uint16列表 uint16_list = [0x3C00, 0x4000, 0xC000] # 对应float16的1.0、2.0、-2.0 # 转换步骤 uint16_arr = np.array(uint16_list, dtype=np.uint16) float16_arr = uint16_arr.view(np.float16) print(float16_arr) # 输出: [ 1. 2. -2.]
view方法不会修改内存中的二进制数据,只是告诉numpy用float16的规则去解释这些位,效率远高于手动解析,适合处理大量数据。
手动解析实现(理解原理用)
如果需要理解float16的IEEE 754编码规则,可以手动实现转换函数。float16的结构为:
- 1位符号位(最高位):0表示正,1表示负
- 5位指数位:偏移量为15(即实际指数 = 指数位数值 - 15)
- 10位尾数位:表示小数部分,规格化数默认整数部分为1
函数实现如下:
def uint16_to_float16(uint_val): # 拆分符号位、指数位、尾数位 sign = (uint_val >> 15) & 0x1 exponent = (uint_val >> 10) & 0x1F mantissa = uint_val & 0x3FF # 处理非规格化数(指数位全0) if exponent == 0: if mantissa == 0: return 0.0 if sign == 0 else -0.0 return (-1)**sign * (mantissa / (2**10)) * (2**(-14)) # 处理无穷大或NaN(指数位全1) elif exponent == 0x1F: if mantissa == 0: return float('inf') if sign == 0 else float('-inf') return float('nan') # 处理规格化数 else: return (-1)**sign * (1 + mantissa / (2**10)) * (2**(exponent - 15)) # 测试用例 print(uint16_to_float16(0x3C00)) # 输出: 1.0 print(uint16_to_float16(0x4000)) # 输出: 2.0 print(uint16_to_float16(0xC000)) # 输出: -2.0 print(uint16_to_float16(0x7C00)) # 输出: inf print(uint16_to_float16(0xFC00)) # 输出: -inf print(uint16_to_float16(0x7E00)) # 输出: nan
内容的提问来源于stack exchange,提问作者Sara N.
相关产品推荐
相关产品推荐

