不同数制之间的相互转换
import json
import os
import struct
import numpy
import numpy as np
import torch
def float32_to_fp8_binary(value, bias=7, E=4, M=3):
"""
:param value: float32类型的值
:param bias: fp8的偏移量
:param E: fp8的指数位数
:param M: fp8的尾数位数
:return: fp8 binary format,such as: 1.34-->00111100
"""
# 将float32转换为uint32
float_as_uint32 = struct.unpack('>I', struct.pack('>f', value))[0]
# 提取float32的符号位
sign = ((float_as_uint32 >> 31) & 0x1)
# 18.5: 0 10000011 00101000000000000000000
# 提取float32的指数部分,并减去127(float32的偏移量),然后将指数转换为FP8所需的格式
exponent = ((float_as_uint32 >> 23) & 0xFF) - 127
# FP8有8位指数,所以需要裁剪指数
if exponent > (2**E-1)-bias:
exponent = (2**E-1)-bias
elif exponent < -bias:
exponent = -bias
exponent += bias
# 提取float32的小数部分,并根据需要进行舍入
fraction = (float_as_uint32 & 0x700000)
# 对小数部分进行裁剪和对齐,并最终合成FP8的表示
sign = bin(sign)[2:]
exponent = ('0' * 8 + bin(exponent)[2:])[-8:][-E:]
fraction = ('0'* 23 + bin(fraction)[2:])[-23:][:M]
fp8 = sign + exponent + fraction
return fp8
def binary_to_hex(binary):
"""
将二进制转换为十六进制
:param binary: 00111100
:return: 0X3C
"""
num_dict = {"10": 'A', "11": 'B', "12": 'C', "13": 'D', "14": 'E', "15": 'F', }
hex_str = ""
for i in range(0, len(binary), 4):
int_data = int(binary[i:i+4], 2)
if int_data > 9:
hex_str += num_dict[str(int_data)]
else:
hex_str += str(int_data)
return hex_str
def float_to_hex(input):
"""
将float转换为hex,需要用到numpy的 tolist() 函数,仅支持float64/32/16
:param input:
:return: (np.float16)0.35 --> '359A' | (np.float32)0.35 --> '3EB33333'
"""
temp = hex(int.from_bytes(input.tobytes(), 'little')).upper().replace('0X', '')
return temp
def uint16_to_float16(input):
"""
将uint16转换为float32
:param input:
:return:
"""
uint16 = bin(input)[2:]
uint16 = ("0" * 16 + uint16)[-16:]
sign = uint16[:1]
fp16_exponent = uint16[1:6]
fp16_fraction = uint16[6:]
fp16_exp_bias = 15
fp32_exp_bias = 127
fp32_exponent = bin(int(fp16_exponent, 2) - fp16_exp_bias + fp32_exp_bias)[2:]
fp32_exponent = ("0" * 8 + fp32_exponent)[-8:]
fp32_fraction = fp16_fraction + "0" * 13
fp32_binary = sign + fp32_exponent + fp32_fraction
fp16_res = struct.unpack('<f', struct.pack('<I', int(fp32_binary, 2)))[0]
return fp16_res
if __name__ == '__main__':
res = binary_to_hex('00111100')
print(res)
res = float_to_hex(np.array([1.23456789], dtype=np.float32))
print(res)
res = float32_to_fp8_binary(1.23456789)
print(res)
res = uint16_to_float16(15744)
print(res)