如何从二进制文件中打印half-precision及bfloat16浮点数值?
如何在Shell中从二进制文件读取并打印16位浮点数(Half-Precision/BFloat16)
由于系统自带的od命令不支持2字节浮点类型,Perl的pack函数也无法直接解析Half-Precision或BFloat16,下面提供两种可行的处理方案:
方案1:使用Python脚本处理
Python的numpy库或原生struct模块结合位运算,能轻松实现两种16位浮点数的解析。
处理Half-Precision(IEEE 754 16位浮点)
方法A:原生struct实现(无需依赖numpy)
保存以下代码为half_reader.py:
#!/usr/bin/env python3 import sys import struct def half_to_float(half): sign = (half >> 15) & 0x1 exponent = (half >> 10) & 0x1F mantissa = half & 0x3FF if exponent == 0: if mantissa == 0: return struct.unpack('!f', struct.pack('!I', sign << 31))[0] exponent = 1 - 15 + 127 mantissa <<= (23 - 10) return struct.unpack('!f', struct.pack('!I', (sign << 31) | (exponent << 23) | mantissa))[0] elif exponent == 0x1F: return struct.unpack('!f', struct.pack('!I', (sign << 31) | (0xFF << 23) | (mantissa << 13)))[0] else: exponent = exponent - 15 + 127 mantissa <<= (23 - 10) return struct.unpack('!f', struct.pack('!I', (sign << 31) | (exponent << 23) | mantissa))[0] with open(sys.argv[1], 'rb') as f: while True: data = f.read(2) if not data: break # 按小端字节序解析,大端替换为'>H' half = struct.unpack('<H', data)[0] print(half_to_float(half))
赋予执行权限后运行:
chmod +x half_reader.py ./half_reader.py c.bin
方法B:numpy简化实现(需安装numpy)
#!/usr/bin/env python3 import sys import numpy as np # 小端字节序用'<f2',大端用'>f2' arr = np.fromfile(sys.argv[1], dtype='<f2') for val in arr: print(val)
处理BFloat16(16位浮点,8位指数)
方法A:原生struct实现
保存以下代码为bfloat16_reader.py:
#!/usr/bin/env python3 import sys import struct def bfloat16_to_float(bf16): sign = (bf16 >> 15) & 0x1 exponent = (bf16 >> 7) & 0xFF mantissa = bf16 & 0x7F if exponent == 0: if mantissa == 0: return struct.unpack('!f', struct.pack('!I', sign << 31))[0] exponent = 1 - 127 + 127 mantissa <<= (23 -7) return struct.unpack('!f', struct.pack('!I', (sign <<31)|(exponent<<23)|mantissa))[0] elif exponent == 0xFF: return struct.unpack('!f', struct.pack('!I', (sign<<31)|(0xFF<<23)|(mantissa<<16)))[0] else: mantissa <<= (23 -7) return struct.unpack('!f', struct.pack('!I', (sign<<31)|(exponent<<23)|mantissa))[0] with open(sys.argv[1], 'rb') as f: while True: data = f.read(2) if not data: break # 按小端字节序解析,大端替换为'>H' bf16 = struct.unpack('<H', data)[0] print(bfloat16_to_float(bf16))
运行方式同Half-Precision脚本。
方法B:numpy简化实现(需numpy 1.20+)
#!/usr/bin/env python3 import sys import numpy as np # 小端字节序用'<bfloat16',大端用'>bfloat16' arr = np.fromfile(sys.argv[1], dtype='<bfloat16') for val in arr: print(val.astype(np.float32))
方案2:使用awk脚本处理(无Python环境时)
如果系统没有Python环境,可以用awk结合位运算实现Half-Precision解析:
保存以下代码为half_reader.awk:
#!/usr/bin/awk -f BEGIN { while ((getline c1 < ARGV[1]) > 0 && (getline c2 < ARGV[1]) > 0) { half = (ord(c2) << 8) | ord(c1) sign = (half >> 15) & 1 exponent = (half >> 10) & 0x1F mantissa = half & 0x3FF if (exponent == 0) { if (mantissa == 0) { val = (sign ? -0.0 : 0.0) } else { exp = 1 - 15 + 127 mant = mantissa << (23 - 10) val = (sign ? -1 : 1) * (mant / (2^23)) * (2^(exp - 127)) } } else if (exponent == 0x1F) { val = (mantissa == 0) ? (sign ? "-inf" : "inf") : "nan" } else { exp = exponent - 15 + 127 mant = mantissa << (23 - 10) val = (sign ? -1 : 1) * (1 + mant / (2^23)) * (2^(exp - 127)) } print val } close(ARGV[1]) } function ord(c) { return sprintf("%d", c) + 0 }
运行命令:
awk -f half_reader.awk c.bin
内容的提问来源于stack exchange,提问作者einpoklum
相关产品推荐
相关产品推荐

