You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从二进制文件中打印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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 00:22:36