2009-09-09 40 views
15

Tôi đang làm việc trên một chương trình mà tôi lưu trữ một số dữ liệu trong một số nguyên và xử lý nó bitwise. Ví dụ, tôi có thể nhận được số 48, mà tôi sẽ xử lý từng bit một. Nói chung, sự kết thúc của các số nguyên phụ thuộc vào sự biểu diễn máy của các số nguyên, nhưng liệu Python có làm bất cứ điều gì để đảm bảo rằng các ints sẽ luôn luôn là nhỏ bé? Hay tôi cần phải kiểm tra độ tin cậy giống như trong C và sau đó viết mã riêng cho hai trường hợp?Endianness của số nguyên trong Python

Tôi hỏi vì mã của tôi chạy trên máy Sun và mặc dù mã đang chạy trên bộ xử lý Intel, tôi có thể phải chuyển sang máy có bộ xử lý mặt trời trong tương lai, mà tôi biết là lớn.

Trả lời

18

Mã số int của Python có cùng độ tin cậy như bộ xử lý mà nó chạy. Mô-đun struct cho phép bạn chuyển đổi các blobs byte thành ints (và viceversa và một số loại dữ liệu khác) theo cách bản địa, nhỏ hoặc cuối lớn, tùy thuộc vào số format string bạn chọn: bắt đầu định dạng với @ hoặc không có kết thúc ký tự để sử dụng tính cuối cùng của bản địa (và kích thước gốc - mọi thứ khác sử dụng kích thước chuẩn), '~' cho gốc, '<' cho nhỏ, '>' hoặc '!' cho người lớn.

Đây là byte-by-byte, không bit-by-bit; không chắc chắn chính xác những gì bạn có ý nghĩa bằng cách xử lý từng bit trong ngữ cảnh này, nhưng tôi cho rằng nó có thể được tương tự như vậy.

Đối nhanh "số lượng lớn" xử lý trong những trường hợp đơn giản, cũng xem xét các mô-đun array - các fromstringtostring phương pháp có thể hoạt động trên số lượng lớn các byte mau lẹ hơn và phương pháp byteswap có thể giúp bạn có được "khác" endianness (có nguồn gốc từ không có nguồn gốc hoặc ngược lại), một lần nữa nhanh chóng và cho một số lượng lớn các mặt hàng (toàn bộ mảng).

+0

có vẻ như python luôn luôn là endian lớn ngay cả trên hệ thống cuối nhỏ. Ví dụ: in 0x0001 sẽ in 1 –

+3

@David 天宇 Wong, bạn đang vẽ các khoản khấu trừ hoàn toàn không chính đáng từ quan sát của bạn - 0x0001 chỉ là ký pháp hex dự phòng cho số nguyên '1', không liên quan gì đến biểu diễn bên trong! –

+0

yup cảm ơn, tôi đã trộn lẫn với tất cả những điều này. Nó có vẻ chỉ là một HEXSTRING của một số nguyên. –

15

Nếu bạn cần xử lý dữ liệu của mình 'bitwise' thì mô-đun bitstring có thể giúp bạn. Nó cũng có thể đối phó với sự kiên định giữa các nền tảng (ít nhất là xây dựng thân cây mới nhất - sẽ được phát hành trong vài ngày tới).

struct module là phương pháp tiêu chuẩn tốt nhất để xử lý sự kết thúc giữa các nền tảng. Ví dụ gói này và giải nén các số nguyên 1, 2, 3 thành hai 'quần short' và một 'dài' (2 và 4 byte trên hầu hết các nền tảng) sử dụng endianness mẹ đẻ:

>>> from struct import * 
>>> pack('hhl', 1, 2, 3) 
'\x00\x01\x00\x02\x00\x00\x00\x03' 
>>> unpack('hhl', '\x00\x01\x00\x02\x00\x00\x00\x03') 
(1, 2, 3) 

Để kiểm tra endianness của nền tảng lập trình bạn có thể sử dụng

>>> import sys 
>>> sys.byteorder 

mà một trong hai sẽ trở lại "big" hoặc "little".

+0

Tôi đã nhìn thấy rất nhiều loại giải thích này (cũng cudo cho sys.byteorder, không biết điều đó) nhưng tôi phải hỏi. Cho phép nói rằng tôi có một số tập tin không rõ rằng tôi muốn đọc làm thế nào tôi có thể biết nếu một số ký tự const là ngắn hoặc dài và/hoặc lớn và ít endian? – Danilo

+1

@Danilo: Nói chung bạn không thể biết được. Để đảo ngược thiết kế một định dạng tệp không xác định, bạn có thể xem dữ liệu và đoán kích thước/độ dài nào có ý nghĩa nhất. Để minh họa, nếu bạn giải nén ví dụ của tôi với sự kết thúc sai mà bạn nhận được (256, 512, 50331648) thay vì (1, 2, 3), đó là một đầu mối hợp lý bạn đã sai ... –

2

Kiểm tra khi nào?

Khi thực hiện các thao tác bitwise, int sẽ có cùng endianess như int mà bạn đưa vào. Bạn không cần phải kiểm tra điều đó. Bạn chỉ cần quan tâm đến điều này khi chuyển đổi sang/từ chuỗi byte, trong cả hai ngôn ngữ, afaik.

Trong Python bạn sử dụng mô-đun cấu trúc cho điều này, thường là struct.pack() và struct.unpack().

+1

Điều quan trọng là vì tôi điều trong mã của tôi như thế này: nếu (a >> 2 & 1) ... elif (b >> 3 & 1) ... nhưng trên bigendian tôi phải viết nếu (a << 2 & 1) ... –

+0

@Gordon: Tôi không nghĩ điều đó đúng. Có một số rắc rối ở đây giữa byte-khôn ngoan lớn và ít endianness và bit-khôn ngoan lớn và ít endianness? Nếu 'a' là một số nguyên thì có thể bạn không phải lo lắng về tính cuối cùng của nó, nó chỉ là câu hỏi về cách bạn tạo nó từ dữ liệu byte thô. –

+0

@Gordon: Không, bạn sẽ không. Big/small-endian không thay đổi thứ tự bit, nhưng thứ tự của * bytes *. Các thao tác dịch chuyển xử lý điều này, cả trong Python và C (vì thực tế chúng đều sử dụng các phép toán dịch chuyển của bộ vi xử lý). –

1

Đoạn sau đây sẽ cho bạn biết nếu mặc định hệ thống của bạn là little endian (nếu không nó là lớn về cuối nhỏ)

import struct 
little_endian = (struct.unpack('<I', struct.pack('=I', 1))[0] == 1) 

Lưu ý, tuy nhiên, điều này sẽ không ảnh hưởng đến hành vi của các nhà khai thác Bitwise: 1<<1 bằng 2 bất kể độ dài mặc định của hệ thống của bạn.

Các vấn đề liên quan