2011-08-19 6 views
10

부동 포인트 : 내 데이터를 IBM 32 비트 부동 점이다 unpack(">f", str)는 IEEE 부동 소수점 풀기위한 실현파이썬 : 압축을 풀고 IBM 32 비트 나는이 같은 파이썬에서 바이너리 파일을 읽고 있었다

from struct import unpack 

ns = 1000 
f = open("binary_file", 'rb') 

while True: 
    data = f.read(ns * 4) 
    if data == '': 
     break 
    unpacked = unpack(">%sf" % ns, data) 
    print str(unpacked) 

숫자

내 질문 : 내 unpack에 IBM 32 비트 부동 소수점 유형 번호의 압축을 해제하려면 어떻게해야합니까?

더 나은 성능을 얻으려면 ctypes을 파이썬으로 확장해도 괜찮습니다.

편집 : 일부 검색을했다 : http://mail.scipy.org/pipermail/scipy-user/2009-January/019392.html

이 매우 유망한 보이지만, 좀 더 효율적 싶어 : 루프 수천의 가능성 수만이 있습니다.

편집 : 아래에 게시 된 답변. 팁 고마워. 먼저 부호없는 4 바이트 정수로 문자열을 압축 해제 한 후이 기능을 사용합니다 :

+7

는 http://mail.scipy.org/pipermail/scipy-user/2009-January/019392.html은 엔디안 문제가 알아야 할, – NPE

+0

@aix를 참조하십시오? –

+1

해당 수정 사항을 답변으로 다시 게시하고 2 일 후 수락하십시오. 질문에 답변을 추가하지 마십시오. – agf

답변

3

나는 내가 그것을 이해 생각 도와 준 모든

def ibm2ieee(ibm): 
    """ 
    Converts an IBM floating point number into IEEE format. 
    :param: ibm - 32 bit unsigned integer: unpack('>L', f.read(4)) 
    """ 
    if ibm == 0: 
     return 0.0 
    sign = ibm >> 31 & 0x01 
    exponent = ibm >> 24 & 0x7f 
    mantissa = (ibm & 0x00ffffff)/float(pow(2, 24)) 
    return (1 - 2 * sign) * mantissa * pow(16, exponent - 64) 

감사합니다!

IBM 부동 소수점 아키텍처, 어떻게 인코딩 및 디코딩 : http://en.wikipedia.org/wiki/IBM_Floating_Point_Architecture

내 솔루션 : 내가 Struct 객체를 사용하기 때문에, 그것은 조금 빠를 수 있습니다, 내가 이런 식으로 생각하는 클래스를 작성, 따라서 unpack fmt는 한 번만 컴파일됩니다. EDIT : 크기를 한 번에 모두 풀어 놓기 때문에 압축을 풀 때 값 비싼 작업이 될 수 있습니다.

from struct import Struct 

class StructIBM32(object): 
    """ 
    see example in: 
    http://en.wikipedia.org/wiki/IBM_Floating_Point_Architecture#An_Example 

    >>> import struct 
    >>> c = StructIBM32(1) 
    >>> bit = '11000010011101101010000000000000' 
    >>> c.unpack(struct.pack('>L', int(bit, 2))) 
    [-118.625] 
    """ 
    def __init__(self, size): 
     self.p24 = float(pow(2, 24)) 
     self.unpack32int = Struct(">%sL" % size).unpack 
    def unpack(self, data): 
     int32 = self.unpack32int(data) 
     return [self.ibm2ieee(i) for i in int32] 
    def ibm2ieee(self, int32): 
     if int32 == 0: 
      return 0.0 
     sign = int32 >> 31 & 0x01 
     exponent = int32 >> 24 & 0x7f 
     mantissa = (int32 & 0x00ffffff)/self.p24 
     return (1 - 2 * sign) * mantissa * pow(16, exponent - 64) 

if __name__ == "__main__": 
    import doctest 
    doctest.testmod() 
+1

래퍼 로직에서 얻는 것보다 많은 시간을 낭비 할 수 있습니다. 실적 주장을하기 전에 벤치마킹을해야합니다. – zwol

관련 문제