2016-09-20 1 views
2

double 유형의 데이터를 십진수 값으로 64 비트 변환하려고합니다. 나는 변환을 위해 https://en.wikipedia.org/wiki/Double-precision_floating-point_format 을 따르고있다.십진수로의 이중 변환 IEEE-754 in Python

나는 다음과 같은 스크립트에서 시도 :

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()에 정밀도가 손실됩니다.

어쨌든 또는 다른 방법으로 해결할 수 있습니까?

+3

당신이 [이 ByteArray (https://docs.python.org/2.7/library/functions.html#bytearray) – janbrohl

+0

문자열 작동하지 않습니다 가능한 경우만큼 사용하는 경우 코드는 훨씬 간단 할 수있다 가능하지만 정수를 사용합니다. 예 :'sign_bit = bytearray (a) [0] >> 7' 가능한 한 대부분의 float 연산에서 정밀도를 잃을 때 float을 사용하지 마십시오. – janbrohl

+0

@janbrohl 제안 해 주셔서 감사합니다. – abhi1610

답변

3

이 변환을 수행하는 쉬운 방법은 struct 모듈을 사용하는 것입니다.

from struct import unpack 

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

출력 파이썬 3에서, 당신은 입력 문자열 및 바이트 문자열로 포장 형식 문자열, 예를 지정해야합니다

0.33333333333333331 

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

당신은 또한 사용할 수 있습니다 b Python 2의 문자열 접두사 (2.6 이상, IIRC). Python 2는 보통 접두어를 무시합니다. 보통 Python 2 문자열은 바이트 문자열이기 때문입니다.

+0

감사합니다. 이 일에 대해 생각하지 않으려면 어리 석다. 그러나, 여전히이 "n"을 할 수있는 것보다 약간의 계산에 사용하고 싶다면? – abhi1610

+1

@ abhi1610'struct.unpack' 함수는 문자열에서 여러 데이터 항목을 언팩하는 데 사용할 수 있기 때문에 튜플을 리턴합니다. 그래서'float' 객체의 값에'n [0]'을 사용했습니다. 파이썬'float'은 표준 [IEEE-754 배정도 64 비트 바이너리]입니다 (https : //en.wikipedia.org/wiki/Double-precision_floating-point_format # IEEE_754_double-precision_binary_floating-point_format : _binary64) 숫자입니다. –

2

너무 많은 작업.

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