Python中二进制和浮点类型互转

文章介绍了如何在Python中自定义函数实现float32和float64类型的浮点数到二进制的转换,以及二进制回转为浮点数的方法。通过理解浮点数的机器表示,分别处理符号位、指数部分和尾数部分,实现了完整的转换过程。此外,还提供了一个函数用于修改浮点数的尾数位。
摘要由CSDN通过智能技术生成

Python中二进制和浮点类型互转

因为有某些需求需要修改float类型的二进制位数,但是发现float32无法直接进行位运算,所以通过学习一些基本的float机器表示方法来自己写了用来转化的一些功能函数。
参考:https://zhuanlan.zhihu.com/p/137616403

float转二进制

#整数部分计算
def int_bin(num):
    ans = ''
    while num != 0:
        ans += str(num&1)
        num = num >> 1
    return ans[::-1]

#小数部分计算
def decimal_bin(num,bit_cnt=24):
    ans = ''
    while num != 0 and len(ans) < bit_cnt:
        tmp = int(num*2)
        ans += str(tmp)
        num = num*2 - tmp
    return ans

#指数部分计算
def exp_bin(exp,bit_cnt = 8):
    ans = ''
    while exp != 0:
        ans += str(exp&1)
        exp = exp >> 1
    while len(ans) != bit_cnt:
        ans += str(0)
    return ans[::-1]

#计算float32转二进制表示,返回结果为string类型,32位
def float32_bin(num):
    if num == 0:
        return '0'*32
    sign = 1
    if num>0:
        sign = 0       #符号位为1
    int_par = int_bin(int(num))
    decimal_par = decimal_bin(num - int(num))
    exp = len(int_par) - 1 + 127    #获取阶码位数,需要让整数位为1
    if len(int_par) == 0:
        dot_pos = decimal_par.find('1') + 1    #没有整数部分,小数要找到对应的1
        exp -= dot_pos - 1      #减的1是为了上面减的1,有整数部分的和没有的不同
        decimal_par = decimal_par[dot_pos:]
    base = int_par[1:] + decimal_par
    while len(base) < 23:      #一共23位尾数位补齐
        base += str(0)
    exp_par = exp_bin(exp)
    ans = str(sign) + exp_par + base
    return ans[:32]

#计算float64转二进制表示,返回结果为string类型,64位
def float64_bin(num):
    if num == 0:
        return '0'*64
    sign = 1
    if num>0:
        sign = 0       #符号位为1
    int_par = int_bin(int(num))
    decimal_par = decimal_bin(num - int(num),bit_cnt=52)
    exp = len(int_par) - 1 + 1023    #获取阶码位数,需要让整数位为1
    if len(int_par) == 0:
        dot_pos = decimal_par.find('1') + 1    #没有整数部分,小数要找到对应的1
        exp -= dot_pos - 1      #减的1是为了上面减的1,有整数部分的和没有的不同
        decimal_par = decimal_par[dot_pos:]
    base = int_par[1:] + decimal_par
    while len(base) < 52:      #一共52位尾数位补齐
        base += str(0)
    exp_par = exp_bin(exp,bit_cnt=11)
    ans = str(sign) + exp_par + base
    return ans[:64]

二进制转float

#二进制部分指数数值计算
def bin_exp(num_str,bit_cnt=8):
    ans = 0
    pivot = 127 if bit_cnt == 8 else 1023
    for i in range(bit_cnt):
        ans <<= 1
        ans |= int(num_str[i])  #从低位开始取
    return ans - pivot    #阶数小于127则为纯小数,此处返回和127的差值

#二进制部分整数数值计算
def bin_int(num_str):
    num_str = '1' + num_str      #把尾数的前导1加上
    ans = 0
    for i in range(len(num_str)):
        ans <<= 1
        ans |= int(num_str[i])
    return ans

#二进制部分小数数值计算
def bin_decimal(num_str):
    ans = 0
    for i in range(len(num_str)):
        ans = (ans + 2**(-(i+1))) if num_str[i]=='1' else ans
    return ans

def bin_float32(num_str):
    sign = 1
    if num_str[0] == '1':
        sign = -1
    exp = bin_exp(num_str[1:9])
    int_par = 0
    if exp < 0:    #纯小数的情况
        decimal_par = bin_decimal('0'*(abs(exp)-1)+'1'+num_str[9:])
    else:
        int_par = bin_int(num_str[9:9+exp])      
        decimal_par = bin_decimal(num_str[9+exp:])
    ans = sign * (int_par+decimal_par)
    return ans

def bin_float64(num_str):
    sign = 1
    if num_str[0] == '1':
        sign = -1
    exp = bin_exp(num_str[1:12],bit_cnt=11)
    int_par = 0
    if exp < 0:    #纯小数的情况
        decimal_par = bin_decimal('0'*(abs(exp)-1)+'1'+num_str[12:])
    else:
        int_par = bin_int(num_str[12:12+exp])      
        decimal_par = bin_decimal(num_str[12+exp:])
    ans = sign * (int_par+decimal_par)
    return ans

float尾数位修改

def modify_float(num,pos_seq,replace_seq,type=32):    #pos_seq为修改位置(位置从尾数位最低位开始计算,0-x),replace_seq为具体修改的值
  if len(pos_seq) != len(replace_seq):
    print("修改序列位置和长度不一致")
    return None
  num_bin = float64_bin(num) if type == 64 else float32_bin(num)
  list_bin = list(num_bin)
  idx = 0
  border = 51 if type == 64 else 22 
  for i in pos_seq:
    if i > border:
      print("超过尾数修改范围")
      return None
    list_bin[type-1-i] = str(replace_seq[idx])
    idx += 1
  num_bin = "".join(list_bin)
  return bin_float64(num_bin) if type == 64 else bin_float32(num_bin)

字符和二进制的互转

#计算单个char(8位字符在数字和二进制之间的转换)
def str_bits(str):
  ret = bin(ord(str))[2:]
  while len(ret) != 8:
    ret = '0' + ret
  return list(ret)
  
def bits_str(bits):
  ret = 0
  tmp = "".join(bits)
  for i in range(len(tmp)):
    ret <<= 1
    ret |= int(tmp[i])
  return chr(ret)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值