2009-12-17 59 views
7

在Python V.2.5.4中,我有一個浮點數,我想獲取和操作(作爲整數)該浮點數的位模式。Python:獲取和操作(作爲整數)位浮點模式

例如,假設我有

x = 173.3125 

在IEEE 754格式中,x的位模式(十六進制)是432D5000

如何獲得&對該位模式進行操作(例如,執行按位操作)?

回答

11

你可以得到你想要的字符串(顯然意味着一個大端,32位的表示; Python的內部使用本地endianity和浮動64位)與struct模塊:

>>> import struct 
>>> x = 173.125 
>>> s = struct.pack('>f', x) 
>>> ''.join('%2.2x' % ord(c) for c in s) 
'432d2000' 

這並沒有讓您執行位操作,但你就可以使用結構再次將字符串映射到一個int :

>>> i = struct.unpack('>l', s)[0] 
>>> print hex(i) 
0x432d2000 

,現在你有一個int,你可以在任何類型的按位運算的使用(請以相反兩個相同的步驟,如果說你需要獲得一個再次float操作後)。

+0

感謝所有提供答案的人。我能夠獲得這兩種技術(1使用ctypes和2使用結構)工作。我不知道的是哪個是可取的。看來,使用pack&unpack結構提供了一種獨立於表示形式的解決方案,但如果我錯了,請糾正我。 – JaysonFix 2009-12-17 16:23:54

+0

另外,我想知道「ctypes」和「struct」解決方案之間是否存在顯着的性能差異。 – JaysonFix 2009-12-17 16:25:43

+0

@JaysonFix:1)你的意思是平臺無關嗎?如果是這樣,並且你明確地討論了endianism,我認爲答案是肯定的。2)對你而言是否有足夠的差異取決於你將要做什麼......數百萬次的操縱?如果是這樣,你應該爲自己設定基準,以便從易用性和可維護性兩個方面來理解它們的含義。 – 2009-12-17 18:04:30

0

我對這個主題不太熟悉,但是您是否嘗試過ctypes模塊?

9

的問題是一個Python浮動對象可能不是一個IEEE 754,因爲它是一個對象(事實上它們,但在內部,他們可以持有取其表示更方便)......

利奧說,你可以做一個類型轉換與ctypes的,所以你執行一個特定的表示(在這種情況下,單精度):

from ctypes import * 
x = 173.3125 
bits = cast(pointer(c_float(x)), POINTER(c_int32)).contents.value 
print hex(bits) 
#swap the least significant bit 
bits ^= 1 

然後回:

y = cast(pointer(c_int32(bits)), POINTER(c_float)).contents.value 
2

使用structxdrlib模塊:

>>> import struct 
>>> x = 173.3125 
>>> rep = struct.pack('>f', x) 
>>> numeric = struct.unpack('>I', rep)[0] 
>>> '%x' %numeric 
'432d5000' 

現在你可以用numeric工作,然後走在相反的方向,讓您的浮點數回來。您必須使用> I(無符號整數)來避免獲得負數。 xdrlib與此類似。

參考文獻:structxdrlib

1

作爲參考,它也可以使用numpy和view。

import numpy 

def fextract(f): 
    bits = numpy.asarray(f, dtype=numpy.float64).view(numpy.int64) 
    if not bits & 0x7fffffffffffffff: # f == +/-0 
    return 0, 0 
    sign = numpy.sign(bits) 
    exponent = ((bits>>52) & 0x7ff) - 1075 
    mantissa = 0x10000000000000 | (bits & 0xfffffffffffff) 
    # from here on f == sign * mantissa * 2**exponent 
    for shift in 32, 16, 8, 4, 2, 1: 
    if not mantissa & ((1<<shift)-1): 
     mantissa >>= shift 
     exponent += shift 
    return sign * mantissa, exponent 

fextract(1.5) # --> 3, -1