2014-04-25 48 views
5

Tôi đã cố gắng làm việc này trong vài ngày, tôi đã đọc một nghìn hướng dẫn và câu hỏi của mọi người, nhưng tôi vẫn không thể tìm ra cách để làm đúng.C# Xoay bit sang vấn đề tràn bên trái

Điều tôi muốn làm là xoay các bit sang trái, đây là một ví dụ.

số gốc = 10.000.001 = 129 gì tôi cần = 00000011 = 3

tôi phải xoay các bit sang trái một số tiền nhất định của thời gian (nó phụ thuộc vào những gì mà người dùng), đây là những gì tôi đã làm:

byte b = (byte)129; 
byte result = (byte)((byte)b << 1); 
Console.WriteLine(result); 

Console.Write("Press any key to continue . . . "); 
Console.ReadKey(true); 

vấn đề với điều này nó mà nó gây ra một lỗi (OverflowException) khi tôi cố gắng sử dụng các nhà điều hành (< <) với con số đó (lưu ý rằng nếu tôi đặt một số mà bit đầu tiên là 0; ví dụ : 3 = 00000011, nó hoạt động như dự định và trả về kết quả là 6.

Vấn đề là, nếu bit đầu tiên là 1, nó sẽ cho tôi lỗi (OverflorException). Tôi biết điều này không xoay, nó chỉ là một chuyển dịch, bit đầu tiên biến mất và vào cuối byte là 0 bật lên, và sau đó tôi có thể thay đổi nó bằng thao tác OR 000000001 để làm cho nó thành 1 (nếu bit đầu tiên là 1, nếu nó là 0 tôi chỉ để nó ở đó).

Bất kỳ ý tưởng nào? Cảm ơn trước!

+1

Có u cố gắng sử dụng các từ khóa không được kiểm soát? http://msdn.microsoft.com/de-de/library/a569z7k8.aspx – CSharpie

+0

Bạn chỉ làm việc đó với byte? Nếu vậy bạn có thể ăn gian một chút bằng cách dịch chuyển như một int và sau đó sử dụng một mặt nạ để cắt bớt nó một khi bạn đã làm xong, có khả năng sử dụng một mặt nạ khác và thay đổi để có được các bit để đưa vào cuối thấp hơn. – Chris

+0

Khi tôi làm điều này, tôi không nhận được một 'OverflowException'. –

Trả lời

4

<< là toán tử thay đổi, không phải là toán tử xoay vòng.

Nếu bạn muốn xoay, bạn có thể sử dụng (với đúc thích hợp):

b = (b >> 7) | ((b & 0x7f) << 1); 

Phần đầu tiên của mà được các bit tận cùng bên trái xuống đến tận cùng bên phải, phần thứ hai chuyển tất cả các trái khác.

or -ing chúng với | kết hợp cả hai.

+1

Bạn sẽ cần một diễn viên trong đó rõ ràng (vì vậy linqpad nói với tôi). – Chris

8

Bạn đang nhận được ngoại lệ tràn vì bạn đang hoạt động trong ngữ cảnh được chọn.

Bạn có thể khắc phục điều đó bằng cách đặt mã trong một bối cảnh không được kiểm soát - hoặc chỉ bằng cách đảm bảo bạn không thực hiện các diễn viên trở lại byte trên một giá trị có thể có nhiều hơn 255. Ví dụ:

int shifted = b << rotateLeftBits; 
int highBits = shifted & 0xff; 
int lowBits = shifted >> 8; // Previously high bits, rotated 
byte result = (byte) (highBits | lowBits); 

Điều này sẽ hoạt động với kích thước xoay lên đến 8. Đối với kích thước lớn hơn, chỉ cần sử dụng rotateLeftBits % 8 (và chuẩn hóa thành số không âm nếu đôi khi bạn có thể muốn xoay sang phải).

+0

Tôi thích điều này để làm việc với số lượng thay đổi khác nhau. :) – Chris

0

Cảm ơn câu trả lời của bạn!

Không lâu sau khi tôi thực hiện bài viết này tôi đã đưa ra một ý tưởng để giải quyết vấn đề này, hãy để tôi chỉ cho bạn (Trước khi bạn hỏi, nó hoạt động!):

byte b = (byte)129; 
b = (byte)((byte)b & 127); 
byte result = (byte)((byte)b << 1); 
result = (byte)((byte)result | 1); 
Console.WriteLine(result); 

gì điều này là, loại bỏ đầu tiên bit (trong trường hợp nếu nó là 1) nó dịch chuyển sang trái mà không (không tạo ra tràn) và khi sự thay đổi kết thúc, nó thay đổi 0 trở lại 1. Nếu bit đầu tiên là 0, nó sẽ di chuyển không (lưu ý rằng đây chỉ là một phần của toàn bộ mã, và vì nó được viết một phần bằng tiếng Tây Ban Nha (ý kiến ​​và biến), tôi nghi ngờ bạn sẽ hiểu được hầu hết, vì vậy tôi quyết định đưa ra phần có vấn đề để hiển thị nó các bạn!

Tôi vẫn sẽ thử những điều bạn đã nói với tôi và xem nó như thế nào, một lần nữa, cảm ơn rất nhiều câu trả lời của bạn!

+0

Tôi không nghĩ điều đó hoàn toàn đúng. Dòng thứ tư của bạn đặt bit thấp thành 1 bất kể bit cao bắt đầu là gì. Vì vậy, ví dụ, mẫu bit 00000001 trở thành 00000011. – paxdiablo

+0

Như tôi đã nói trước đây, đây chỉ là một phần của một mã lớn hơn, trong mã hoàn chỉnh, có một hoạt động của số AND 128 để biết bit đầu tiên là 1 hay 0, và tùy thuộc vào kết quả đó, sẽ nhập IF hoặc ELSE, trong IF bị bệnh làm điều đó tôi đã viết xuống, trên ELSE bệnh chỉ cần làm << hoạt động bình thường. – Lobialkon

0

hãy thử chức năng này - xoay theo cả hai hướng (trái và xoay bên phải của một giá trị 8 bit) [Tôi không thử nghiệm chức năng đó!]

// just for 8Bit values (byte) 
byte rot(byte value, int rotation) 
    { 
     rotation %= 8; 

     int result; 
     if(rotation < 0) 
     { 
      result = value << (8 + rotation); 
     } 
     else 
     { 
      result = value << rotation; 
     } 

     byte[] resultBytes = BitConverter.GetBytes(result); 
     result = resultBytes[0] | resultBytes[1]; 

     return (byte)result; 
    } 

short rot(short value, int rotation) { ... } 
int rot(int value, int rotation) { ... } 
Các vấn đề liên quan