2009-12-17 30 views
7

Trong Python V.2.5.4, tôi có một float, và tôi muốn lấy và thao tác (như một số nguyên) mẫu bit của float đó.Python: lấy và thao tác (như số nguyên) mẫu bit của phao

Ví dụ, giả sử tôi có

x = 173.3125 

Trong định dạng IEEE 754, bit mẫu x (trong hệ thập lục phân) là 432D5000.

Tôi làm cách nào để có được thao tác & (ví dụ: thực hiện thao tác bitwise) trên mẫu bit đó?

Trả lời

11

Bạn có thể nhận được chuỗi bạn muốn (rõ ràng ngụ ý một đại diện 32-bit lớn, cuối cùng; Python nội bộ sử dụng endianity mẹ đẻ và 64-bit cho phao) với struct mô-đun:

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

này chưa cho phép bạn thực hiện các hoạt động Bitwise, nhưng bạn có thể sau đó sử dụng struct một lần nữa để lập bản đồ chuỗi thành một int :

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

và bây giờ bạn có một int mà bạn có thể sử dụng trong bất kỳ loại hoạt động Bitwise (theo cùng hai bước ngược lại nếu sau khi cho biết các hoạt động bạn cần để có được một float một lần nữa).

+0

Nhờ tất cả những người đã cung cấp câu trả lời. Tôi đã có thể nhận được cả hai kỹ thuật (1 sử dụng ctypes, và 2 sử dụng struct) để làm việc. Những gì tôi không biết là điều thích hợp hơn. Nó xuất hiện rằng bằng cách sử dụng gói & giải nén của struct cung cấp một giải pháp đại diện độc lập, nhưng sửa tôi nếu tôi sai. – JaysonFix

+0

Ngoài ra, tôi đã tự hỏi liệu có sự khác biệt đáng kể về hiệu suất giữa các giải pháp "ctypes" và "struct" hay không. – JaysonFix

+0

@JaysonFix: 1) bạn có ý nghĩa độc lập với nền tảng không? Nếu vậy, và bạn rõ ràng về chủ nghĩa endian, tôi nghĩ câu trả lời là có.2) Liệu có đủ sự khác biệt đối với bạn tùy thuộc vào những gì bạn định làm ... hàng triệu thao tác? Nếu vậy, bạn nên chuẩn bị cho chính mình, do đó bạn sẽ hiểu được những tác động, cả về hiệu suất về mặt dễ sử dụng và khả năng bảo trì. –

0

Tôi không quá thạo về chủ đề này, nhưng bạn đã thử mô-đun ctypes chưa?

9

Vấn đề là một đối tượng phao Python có thể không phải một IEEE 754, bởi vì nó là một đối tượng (trong thực tế họ đang có, nhưng trong nội bộ họ có thể giữ bất cứ đại diện là thuận tiện hơn) ...

Như leo nói, bạn có thể làm một loại đúc với ctypes, vì vậy bạn đang thực thi một đại diện cụ thể (trong trường hợp này, độ chính xác duy nhất):

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 

Và sau đó trở lại:

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

Sử dụng struct hoặc xdrlib mô-đun:

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

Bây giờ bạn có thể làm việc với numeric, và sau đó đi theo hướng ngược lại để có được số điểm nổi của bạn trở lại. Bạn phải sử dụng> I (unsigned int) để tránh nhận số âm. xdrlib tương tự.

Tham chiếu: struct, xdrlib.

1

Để tham khảo, bạn cũng có thể sử dụng gọn gàng và xem.

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 
Các vấn đề liên quan