복붙노트

[PYTHON] 파이썬에서 float의 이진 표현 (16 진수가 아닌 비트)

PYTHON

파이썬에서 float의 이진 표현 (16 진수가 아닌 비트)

문자열을 32 비트 부동 소수점의 이진 IEEE 754 표현으로 가져 오는 방법은 무엇입니까?

1.00 -> '00111111100000000000000000000000'

해결법

  1. ==============================

    1.구조체 패키지를 사용하면 다음과 같이 할 수 있습니다.

    구조체 패키지를 사용하면 다음과 같이 할 수 있습니다.

    import struct
    def binary(num):
        return ''.join(bin(ord(c)).replace('0b', '').rjust(8, '0') for c in struct.pack('!f', num))
    

    이것은 네트워크 byte-ordered float로 패킹 한 다음 결과 바이트 각각을 8 비트 이진 표현으로 변환하고 연결합니다.

    >>> binary(1)
    '00111111100000000000000000000000'
    

    편집하다: 설명을 확장하라는 요청이있었습니다. 나는 중간 변수를 사용하여 이것을 확장하여 각 단계에 주석을 달 것이다.

    def binary(num):
        # Struct can provide us with the float packed into bytes. The '!' ensures that
        # it's in network byte order (big-endian) and the 'f' says that it should be
        # packed as a float. Alternatively, for double-precision, you could use 'd'.
        packed = struct.pack('!f', num)
        print 'Packed: %s' % repr(packed)
    
        # For each character in the returned string, we'll turn it into its corresponding
        # integer code point
        # 
        # [62, 163, 215, 10] = [ord(c) for c in '>\xa3\xd7\n']
        integers = [ord(c) for c in packed]
        print 'Integers: %s' % integers
    
        # For each integer, we'll convert it to its binary representation.
        binaries = [bin(i) for i in integers]
        print 'Binaries: %s' % binaries
    
        # Now strip off the '0b' from each of these
        stripped_binaries = [s.replace('0b', '') for s in binaries]
        print 'Stripped: %s' % stripped_binaries
    
        # Pad each byte's binary representation's with 0's to make sure it has all 8 bits:
        #
        # ['00111110', '10100011', '11010111', '00001010']
        padded = [s.rjust(8, '0') for s in stripped_binaries]
        print 'Padded: %s' % padded
    
        # At this point, we have each of the bytes for the network byte ordered float
        # in an array as binary strings. Now we just concatenate them to get the total
        # representation of the float:
        return ''.join(padded)
    

    그리고 몇 가지 예를 들어 보겠습니다.

    >>> binary(1)
    Packed: '?\x80\x00\x00'
    Integers: [63, 128, 0, 0]
    Binaries: ['0b111111', '0b10000000', '0b0', '0b0']
    Stripped: ['111111', '10000000', '0', '0']
    Padded: ['00111111', '10000000', '00000000', '00000000']
    '00111111100000000000000000000000'
    
    >>> binary(0.32)
    Packed: '>\xa3\xd7\n'
    Integers: [62, 163, 215, 10]
    Binaries: ['0b111110', '0b10100011', '0b11010111', '0b1010']
    Stripped: ['111110', '10100011', '11010111', '1010']
    Padded: ['00111110', '10100011', '11010111', '00001010']
    '00111110101000111101011100001010'
    
  2. ==============================

    2.못 생겼어 ...

    못 생겼어 ...

    >>> import struct
    >>> bin(struct.unpack('!i',struct.pack('!f',1.0))[0])
    '0b111111100000000000000000000000'
    

    기본적으로, 나는 struct 모듈을 사용하여 float를 int로 변환했다.

    다음은 ctypes를 사용하여 약간 더 나은 방법입니다.

    >>> import ctypes
    >>> bin(ctypes.c_uint.from_buffer(ctypes.c_float(1.0)).value)
    '0b111111100000000000000000000000'
    

    기본적으로, 나는 플로트를 만들고 동일한 메모리 위치를 사용하지만, 나는 c_uint로 태그를 붙인다. c_uint의 값은 내장 빈 함수를 사용할 수있는 파이썬 정수입니다.

  3. ==============================

    3.bitstring 모듈을 사용하는 다른 솔루션을 찾았습니다.

    bitstring 모듈을 사용하는 다른 솔루션을 찾았습니다.

    import bitstring
    f1 = bitstring.BitArray(float=1.0, length=32)
    print f1.bin
    

    산출:

    00111111100000000000000000000000
    
  4. ==============================

    4.이 문제는 두 부분으로 나누어보다 명확하게 처리됩니다.

    이 문제는 두 부분으로 나누어보다 명확하게 처리됩니다.

    첫 번째는 해당 비트 패턴을 사용하여 float를 int로 변환하는 것입니다.

    def float32_bit_pattern(value):
        return sum(ord(b) << 8*i for i,b in enumerate(struct.pack('f', value)))
    

    다음으로 int를 문자열로 변환합니다.

    def int_to_binary(value, bits):
        return bin(value).replace('0b', '').rjust(bits, '0')
    

    이제 그들을 결합하십시오 :

    >>> int_to_binary(float32_bit_pattern(1.0), 32)
    '00111111100000000000000000000000'
    
  5. ==============================

    5.완전을 기하기 위해 다음을 사용하여 numpy로이 작업을 수행 할 수 있습니다.

    완전을 기하기 위해 다음을 사용하여 numpy로이 작업을 수행 할 수 있습니다.

    f = 1.00
    int32bits = np.asarray(f, dtype=np.float32).view(np.int32).item()  # item() optional
    

    그런 다음 b 형식 지정자를 사용하여 패딩을 사용하여이를 인쇄 할 수 있습니다

    print('{:032b}'.format(int32bits))
    
  6. ==============================

    6.비슷한 질문을 많이 읽은 후 필자가 원했던 것을 무언가 적어 보았습니다.

    비슷한 질문을 많이 읽은 후 필자가 원했던 것을 무언가 적어 보았습니다.

    f = 1.00
    negative = False
    if f < 0:
        f = f*-1
        negative = True
    
    s = struct.pack('>f', f)
    p = struct.unpack('>l', s)[0]
    hex_data =  hex(p)
    
    scale = 16
    num_of_bits = 32
    binrep = bin(int(hex_data, scale))[2:].zfill(num_of_bits)
    if negative:
        binrep = '1' + binrep[1:]
    

    binrep이 결과입니다. 각 부분에 대해 설명합니다.

    f = 1.00
    negative = False
    if f < 0:
        f = f*-1
        negative = True
    

    음수 일 경우 숫자를 양수로 변환하고 음수를 음수로 설정합니다. 그 이유는 양수 및 음수 바이너리 표현의 차이가 첫 번째 비트에 불과하기 때문에 음수로 전체 프로세스를 수행 할 때 잘못된 점을 파악하는 것보다 더 간단한 방법이었습니다.

    s = struct.pack('>f', f)                          #'?\x80\x00\x00'
    p = struct.unpack('>l', s)[0]                     #1065353216
    hex_data =  hex(p)                                #'0x3f800000'
    

    s는 2 진수 f의 16 진수 표현입니다. 그러나 그것은 내가 필요한 예쁜 형태가 아닙니다. Th가 p가 들어오는 곳입니다. 헥스의 int 표현입니다. 그리고 예쁜 헥스를 얻기위한 다른 변환.

    scale = 16
    num_of_bits = 32
    binrep = bin(int(hex_data, scale))[2:].zfill(num_of_bits)
    if negative:
        binrep = '1' + binrep[1:]
    

    scale은 16 진수의 기본 16입니다. num_of_bits는 32이고, float는 32 비트이므로 나중에 0으로 추가 자리를 채우기 위해 사용됩니다.이 질문에서 binrep 코드를 얻습니다. 숫자가 음수이면 첫 번째 비트 만 변경하십시오.

    나는 이것이 추한 것을 알고 있지만, 나는 좋은 방법을 찾지 못했고 나는 그것을 빨리 필요로했다. 의견 환영합니다.

  7. ==============================

    7.내 생각에 .format을 비트의 가장 쉬운 표현으로 사용할 수 있습니다.

    내 생각에 .format을 비트의 가장 쉬운 표현으로 사용할 수 있습니다.

    내 코드는 다음과 같습니다.

    def fto32b(flt):
    # is given a 32 bit float value and converts it to a binary string
    if isinstance(flt,float):
        # THE FOLLOWING IS AN EXPANDED REPRESENTATION OF THE ONE LINE RETURN
                #   packed = struct.pack('!f',flt) <- get the hex representation in (!)Big Endian format of a (f) Float
                #   integers = []
                #   for c in packed:
                #       integers.append(ord(c))    <- change each entry into an int
                #   binaries = []
                #   for i in integers:
                #       binaries.append("{0:08b}".format(i)) <- get the 8bit binary representation of each int (00100101)
                #   binarystring = ''.join(binaries) <- join all the bytes together
                #   return binarystring
        return ''.join(["{0:08b}".format(i) for i in [ord(c) for c in struct.pack('!f',flt)]])
    return None
    

    산출:

    >>> a = 5.0
    '01000000101000000000000000000000'
    >>> b = 1.0
    '00111111100000000000000000000000'
    
  8. ==============================

    8.이러한 답변 중 일부는 Python 3로 작성된 것처럼 작동하지 않거나 음의 부동 소수점 숫자를 올바르게 나타내지 않았습니다. 나는 나를 위해 일할 다음을 발견했다. (이것은 내가 필요로하는 64 비트 표현을 제공하지만)

    이러한 답변 중 일부는 Python 3로 작성된 것처럼 작동하지 않거나 음의 부동 소수점 숫자를 올바르게 나타내지 않았습니다. 나는 나를 위해 일할 다음을 발견했다. (이것은 내가 필요로하는 64 비트 표현을 제공하지만)

    def float_to_binary_string(f):
        def int_to_8bit_binary_string(n):
            stg=bin(n).replace('0b','')
            fillstg = '0'*(8-len(stg))
            return fillstg+stg
        return ''.join( int_to_8bit_binary_string(int(b)) for b in struct.pack('>d',f) )
    
  9. ==============================

    9.이것은 묻는 것보다 조금 더 많았지 만,이 항목을 발견했을 때 필요한 것이 었습니다. 이 코드는 IEEE 754 32 비트 부동 소수점의 가수, 기준 및 부호를 제공합니다.

    이것은 묻는 것보다 조금 더 많았지 만,이 항목을 발견했을 때 필요한 것이 었습니다. 이 코드는 IEEE 754 32 비트 부동 소수점의 가수, 기준 및 부호를 제공합니다.

    import ctypes
    def binRep(num):
        binNum = bin(ctypes.c_uint.from_buffer(ctypes.c_float(num)).value)[2:]
        print("bits: " + binNum.rjust(32,"0"))
        mantissa = "1" + binNum[-23:]
        print("sig (bin): " + mantissa.rjust(24))
        mantInt = int(mantissa,2)/2**23
        print("sig (float): " + str(mantInt))
        base = int(binNum[-31:-23],2)-127
        print("base:" + str(base))
        sign = 1-2*("1"==binNum[-32:-31].rjust(1,"0"))
        print("sign:" + str(sign))
        print("recreate:" + str(sign*mantInt*(2**base)))
    
    binRep(-0.75)
    

    산출:

    bits: 10111111010000000000000000000000
    sig (bin): 110000000000000000000000
    sig (float): 1.5
    base:-1
    sign:-1
    recreate:-0.75
    
  10. from https://stackoverflow.com/questions/16444726/binary-representation-of-float-in-python-bits-not-hex by cc-by-sa and MIT license