在 Python 中双重转换为十进制值 IEEE-754

Double Conversion to decimal value IEEE-754 in Python

我正在尝试将我的 double 类型数据 64 位长转换为十进制值。我正在关注 https://en.wikipedia.org/wiki/Double-precision_floating-point_format 为转换。

我已经在以下脚本中尝试过:

a = '\x3f\xd5\x55\x55\x55\x55\x55\x55'  # Hexbyte representation of 1/3 value in double

sign_bit =  bin(ord(a[0])).replace('0b', '').rjust(8, '0')[0]
sign = -1 ** int(sign_bit)
print sign    # Sign bit

# Next 11 bits for exponent calculation
exp_bias = 1023
a11 = bin(ord(a[0])).replace('0b', '').rjust(8, '0')[1:] + bin(ord(a[1])).replace('0b', '').rjust(8, '0')[:4]
exp = int(a11, 2)
print exp

# Next 52 bits for fraction calculation
fraction = bin(ord(a[1])).replace('0b', '').rjust(8, '0')[4:] + bin(ord(a[2])).replace('0b', '').rjust(8, '0') \
           + bin(ord(a[3])).replace('0b', '').rjust(8, '0') + bin(ord(a[4])).replace('0b', '').rjust(8, '0') \
            + bin(ord(a[5])).replace('0b', '').rjust(8, '0') + bin(ord(a[6])).replace('0b', '').rjust(8, '0') \
            + bin(ord(a[7])).replace('0b', '').rjust(8, '0')
print len(fraction), fraction
fract = str(int(fraction, 2))
print len(fract), fract
fin = repr(float(fract)/ 10 ** 16)
print type(fin), fin   # 16 digit precision

# final value calculation according equation 
# eq = (-1)^sign * 2 ^(exp- exp_bias) * (1 + fin)
val = 2 ** (exp - exp_bias) * float(fin)    # Looses precision
print val

请任何人帮助我解决这个问题。我无法理解我哪里错了?因为我可以通过使用 repr() 获得精确的分数值,但每当尝试将其用于方程式时,它都会在 float().

中失去精度

有什么解决办法吗?

进行这种转换的简单方法是使用 struct 模块。

from struct import unpack

a = '\x3f\xd5\x55\x55\x55\x55\x55\x55'
n = unpack('>d', a)
print '%.18f' % n[0]

输出

0.33333333333333331

在Python3中,需要指定输入字符串和打包格式字符串为字节串,eg

a = b'\x3f\xd5\x55\x55\x55\x55\x55\x55'
n = unpack(b'>d', a)
print(format(n[0], '.18f'))

您还可以在 Python 2(从 2.6 及更高版本,IIRC)中使用 b 字符串前缀。 Python 2 只是忽略该前缀,因为正常的 Python 2 字符串是字节字符串。

工作量太大。

>>> import struct
>>> struct.unpack('>d', '\x3f\xd5\x55\x55\x55\x55\x55\x55')[0]
0.3333333333333333