2012-12-09 28 views
5

tôi có bộ phận sau đây mà tôi cần phải làm thường xuyên:Làm thế nào để biến một bộ phận thành một sự thay đổi bitwise khi sức mạnh của hai?

int index = pos/64; 

Division có thể tốn kém ở mức độ cpu. Tôi hy vọng có một cách để làm điều đó với sự thay đổi bitwise. Tôi cũng muốn hiểu làm thế nào bạn có thể đi từ phân chia sang ca, nói cách khác, tôi không muốn chỉ ghi nhớ biểu thức bitwise.

+1

'pos/(2^6)' => 'pos >> 6'; 'pos/(2^1)' => 'pos >> 1' – irrelephant

+1

Phân chia không nên tốn kém ở cấp cpu. – ceklock

+0

Bạn có thể nhầm lẫn về "phân chia là tốn kém". Hãy nhớ trích dẫn nổi tiếng của Donald Knuth: [Tối ưu hóa sớm là gốc rễ của tất cả các Ác ma] (http://en.wikipedia.org/wiki/Program_optimization) – paulsm4

Trả lời

7

int index = pos >> 6 sẽ làm điều đó, nhưng điều này là không cần thiết. Bất kỳ trình biên dịch hợp lý nào cũng sẽ làm việc này cho bạn. Chắc chắn trình biên dịch Sun/Oracle sẽ.

Quy tắc chung là i/(2^n) có thể được triển khai với i >> n. Tương tự, i*(2^n)i << n.

Bạn cần phải quan tâm đến số đại diện tiêu cực nếu i được ký. Ví dụ. twos-bổ sung tạo ra kết quả hợp lý (nếu thay đổi phải là số học - bit dấu hiệu sao chép). Đã ký cường độ không.

+0

Bạn đúng - làm "thay đổi" để tránh "phân chia" là không cần thiết và sai đầu. IMHO ... – paulsm4

+3

Trình biên dịch sẽ chỉ tối ưu hóa nếu nó là chữ. Nếu nó là một biến nó sẽ không tối ưu hóa bất cứ điều gì và bạn có thể dễ dàng thực thi thông qua logic của bạn rằng biến là một sức mạnh của hai. Sau đó, bạn tự mình tối ưu hóa. – TraderJoeChicago

2

Trình biên dịch sẽ triển khai nó theo cách hiệu quả nhất, miễn là bạn hiểu những gì bạn cần và yêu cầu trình biên dịch thực hiện chính xác điều đó. Nếu ca là cách hiệu quả nhất trong trường hợp này, trình biên dịch sẽ sử dụng ca.

Hãy nhớ rằng nếu bạn đang thực hiện đã ký chia (tức là pos được ký), sau đó nó không thể được thực hiện hoàn toàn bởi một ca. Việc tự thay đổi sẽ tạo ra các kết quả không hợp lệ cho các giá trị âm của pos. Nếu trình biên dịch quyết định sử dụng thay đổi cho các hoạt động này, nó cũng sẽ phải thực hiện một số sửa đổi sau ca trên kết quả trung gian để làm cho nó đồng ý với các yêu cầu của đặc tả ngôn ngữ.

Vì lý do này, nếu bạn đang thực sự tìm kiếm hiệu quả tối đa có thể có của hoạt động phân chia, bạn phải nhớ không sử dụng các loại đã ký một cách vô ý. Thích sử dụng các loại chưa ký bất cứ khi nào có thể và chỉ sử dụng các loại đã ký khi bạn cần.

P.S. AFAIK, Java thực hiện phân chia Euclide, có nghĩa là các nhận xét trên không áp dụng cho Java. Sự phân chia Euclide được thực hiện một cách chính xác bởi sự dịch chuyển trên một ước số âm trong biểu diễn bù 2. Các nhận xét trên sẽ áp dụng cho C/C++.

0

http://www.java-samples.com/showtutorial.php?tutorialid=58

Đối với mỗi sức mạnh của 2 bạn muốn chia, phải thay đổi nó một lần. Vì vậy, để chia cho 4 bạn sẽ phải thay đổi hai lần. Để chia cho 8 ca phải 3 lần. Chia cho 16 lần thay đổi 4 lần. 32 -> 5 lần. 64 -> 6 lần. Vì vậy, để chia cho 64 bạn có thể thay đổi quyền 6 lần. myvalue = myvalue >> 6;

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