web-dev-qa-db-ja.com

Python(16進数ではないビット)の浮動小数点のバイナリ表現

文字列を32ビット浮動小数点のバイナリIEEE 754表現として取得する方法は?

1.00-> '00111111100000000000000000000000'

46

structパッケージでそれを行うことができます:

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

これは、ネットワークのバイト順フロートとしてパックし、結果の各バイトを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'
53
Dan Lecocq

これはいものです...

>>> 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'

基本的に、floatを作成し、同じメモリロケーションを使用しますが、c_uintc_uintの値はpython整数で、組み込みのbin関数を使用できます。

29
mgilson

bitstring モジュールを使用した別のソリューションが見つかりました。

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

出力:

00111111100000000000000000000000
20

この問題は、2つの部分に分けることで、よりきれいに処理されます。

1つ目は、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'
8
Mark Ransom

完全を期すために、次を使用してnumpyでこれを実現できます。

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

次に、b形式指定子を使用して、これをパディングで印刷できます。

print('{:032b}'.format(int32bits))
5
Eric

たくさんの同様の質問を閲覧した後、私が望んでいたことを願って何かを書いた。

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

負の場合は数値を正に変換し、変数の負をfalseに設定します。これは、正と負のバイナリ表現の違いが最初のビットにあるためであり、これは負の数でプロセス全体を実行するときに何がうまくいかないかを理解するよりも簡単な方法でした。


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

sは、バイナリfの16進表現です。しかし、それは私が必要とするきれいな形ではありません。 pの出番です。これは、16進数sの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で埋めて32にするために使用されます。 this question からbinrepのコードを取得しました。数値が負の場合、最初のビットを変更します。


私はこれがいことを知っていますが、ニースの方法を見つけられなかったので、それを早く必要としました。コメントを歓迎します。

これは尋ねられたよりも少し多いですが、このエントリを見つけたときに必要なものでした。このコードは、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
1
johnml1135

これらの回答のいくつかは、Python 3で書かれたように機能しなかったか、負の浮動小数点数の正しい表現を提供しませんでした。私が必要なものである表現)

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) )
0
dkhammond

私の意見では、ビットの最も簡単な表現に.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'
0
Robert Hughes