2011-01-25 20 views
6

Đây là câu hỏi được hỏi bởi một đại diện của NVIDIA tại hội chợ nghề nghiệp:Hoán đổi từng cặp bit theo byte

Viết mã nhỏ, hiệu quả để hoán đổi từng cặp bit trong một byte; ví dụ: 10 11 01 10 phải trở thành 01 11 10 01.

Có cách nào hiệu quả hơn để thực hiện việc này không bằng cách thực hiện vòng lặp for thông qua mọi chỉ mục khác? Mã của tôi là nhỏ, nhưng tôi không thể nghĩ có bao nhiêu "hiệu quả" này có thể có thể nhận được hơn một vòng lặp ... Tôi đoán có thể có một cách để sử dụng XOR để tránh một vòng lặp, nhưng tôi không thể tìm ra.

Cảm ơn!

+0

It 'wasn't' một câu hỏi? Tôi không thấy nó ... –

+1

@MrDisappointment Tôi nghi ngờ rằng nếu đó là một câu hỏi, Mehrdad sẽ vi phạm thỏa thuận bằng văn bản hoặc yêu cầu không chia sẻ câu hỏi với người khác. – Phrogz

+0

@MrDisappointment: LOL xin lỗi, lỗi đánh máy; cố định XD ... @ Phrogs: Không có thỏa thuận như vậy hay bất cứ điều gì, đó là một hội chợ nghề nghiệp mở với một trăm hoặc hai người; không có chữ ký hoặc bất cứ thứ gì thuộc loại này. :) – Mehrdad

Trả lời

11

Bạn có thể sử dụng bảng tra cứu 256 mục nhập.

Cách khác, ((x & 0x55) << 1) | ((x & 0xAA) >> 1).

+0

+1. Nếu đó là tốc độ bạn muốn, bảng tra cứu là câu trả lời. Nó sử dụng 256 byte cho một bảng tra cứu, nhưng, như với hầu hết các tối ưu hóa, đó là một không gian/thời gian thương mại-off. Nếu bạn không muốn lãng phí không gian đó, bạn sẽ không nhận được bất kỳ nhanh hơn một vài thay đổi và hoạt động bit. – paxdiablo

+3

Hãy coi chừng loại 'đã ký', tất nhiên. –

+1

+1 Tôi nghĩ rằng đó là giải pháp thứ hai, vì nó là ngắn gọn nhất, và rất hiệu quả ... argh, dễ dàng và khó khăn như vậy. : ( – Mehrdad

1

Tra cứu bảng (trừ khi có một số giải pháp cụ thể về NVIDA mà anh đang tìm kiếm).

+0

Nó không tìm kiếm giải pháp cụ thể của NVIDIA, nhưng nó đang tìm kiếm mã * và * nhỏ nhanh ... liệu giải pháp tra cứu bảng có được tính không? (mặc dù thừa nhận tôi đã không nghĩ về nó ...) – Mehrdad

+0

@ Mcrdad: Tra cứu bảng chỉ là một "điều đầu tiên đến với tâm trí" với các loại vấn đề. Chắc chắn có thể có một chút tốt hơn, thông minh hack. Bạn cũng có thể xem xét một bảng 16 byte nhỏ hơn (hoặc thậm chí 8 byte) có thể kết hợp với một số hoạt động thay đổi/mặt nạ để tìm kiếm 4 bit cùng một lúc. Tôi không chắc chỗ ngọt có thể ở đâu. –

12

Something như thế này nên làm việc

(i >> 1) & 01010101 + (i << 1) & 10101010 

i >> 1 thay đổi tất cả mọi thứ bằng 1 chút về bên phải, và & 01010101 lá chỉ bit tại thậm chí vị trí.
Giao dịch phần thứ hai với các vị trí bit lẻ trong cùng một fasion.

Không chắc chắn hiệu quả của nó.

+0

+1 Điều này là darn thông minh, cảm ơn ... Tôi đã suy nghĩ của một số cách để sử dụng thay đổi chút nhưng không thể tìm ra nó. Cool !! :) – Mehrdad

+0

Vâng, tôi thích | toán tử cho toán tử + nhưng cùng một giải pháp. Và tất nhiên mã của bạn là giả cho đại diện base-2. – CashCow

0

Vì chỉ có 256 kết hợp có thể trong một byte, điều này có vẻ giống như một ứng cử viên tốt cho việc sử dụng giải pháp dựa trên bảng tra cứu cho bất kỳ thời điểm nào khi tốc độ thực hiện liên tục quan trọng hơn so với thời gian tính trước và/hoặc sử dụng bộ nhớ tổng.

Ví dụ:

lookupTable[00000000] = 00000000 
lookupTable[00000001] = 00000010 
lookupTable[00000010] = 00000001 
... 
+0

Chắc chắn không phải mã nhỏ. :( – Mehrdad

+0

Chắc chắn không phải tôi đồng ý, nhưng hãy nhớ rằng mã nhỏ không phải lúc nào cũng là mã hiệu quả và hiệu quả không phải lúc nào cũng nhỏ. – Coxy

+0

Lỗi bộ nhớ cache là một vấn đề với bảng tra cứu nói chung. Tôi nghĩ rằng –

2

Nếu không có bảng tra cứu (hoặc để tạo điều ở nơi đầu tiên), bạn cũng có thể:

  • chuyển trái và AND với mặt nạ trái-bit (10101010)
  • shift right và AND với mặt nạ bit phải (01010101)
  • HOẶC kết quả với nhau.

chuyển trái là 01 10 11 00 đeo mặt nạ với 10101010 ban cho chúng ta 00 10 10 00

chuyển quyền (bản gốc) là đeo mặt nạ với 01.010.101 cho chúng ta 01 01 00 01

HOẶC kết quả của chúng tôi cùng nhau

Vì vậy, trong C hoặc C++ bạn có thể làm

unsigned char bitswap(unsigned char uch) 
{ 
    return ((uch<<1) & 0xAA) | (uch>>1) & 0x55); 
} 

Chỉ cần chạy mà cho tất cả các giá trị từ 0x00 đến 0xFF (đảm bảo vòng lặp của bạn chấm dứt!) Để tạo ra "bảng" của bạn.

+0

Cảm ơn bạn đã giải thích! – Chayemor

1

Đối với 32-bit interger trong java ..

public int swapOddEvenbits(int x) 
{ 
    return ( ((x & 0xaaaaaaaa) >> 1 | ((x & 0X55555555) << 1)); 

} 

Nếu bạn đang làm việc với 64-bit, bạn sẽ cần phải thay đổi mặt nạ ..