2008-09-22 34 views
5

Tôi muốn luônYêu cầu được gán một số dương với tất cả các giá trị có thể cho lareValue1 và largeValue2 (đây là ít nhất 1).Tôi có thể ngăn chặn tràn số nguyên trong C# bằng cách sử dụng dịch chuyển phải không dấu?

Tuyên bố sau đây gây ra một lỗi tràn bộ đệm:

int alwaysPositive = (largeValue1 + largeValue2)/2; 

Tôi biết tôi có thể ngăn chặn nó bằng cách trừ đi và nói thêm:

int alwaysPositive = largeValue1 + ((largeValue2 - largeValue1)/2); 

Nhưng trong ngôn ngữ lập trình khác tôi có thể sử dụng một bitshift unsigned làm mẹo:

int alwaysPositive3 = (largeValue1 + largeValue2) >>> 1; 

Làm cách nào để thực hiện điều này trong C#?


Câu trả lời dưới đây giải quyết được vấn đề. Có lẽ rất nhiều cách để làm điều này, nhưng tất cả chúng (bao gồm cả các giải pháp của tôi) có một điểm chung: tất cả chúng đều trông khó hiểu.

+0

Tha thứ cho sự thiếu hiểu biết của tôi, nhưng tại sao bạn lại muốn làm điều này? –

+0

Lý do tôi cố gắng làm điều này là phát minh lại bánh xe: thực hiện tìm kiếm nhị phân. Tại sao tôi lại viết phiên bản của riêng mình? Tôi không biết ... – Paco

+0

Chỉ cần thông tin, các mẫu mã của bạn làm những việc khác nhau. Tôi nghĩ rằng bạn muốn dấu ngoặc đơn trong lần đầu tiên. PS. Bạn có được lấy cảm hứng từ http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html không? –

Trả lời

0

Bạn có thể sử dụng uints:

uint alwaysPositive = (uint)(largeValue1 + largeValue2)/2; 
+0

Điều này sẽ vẫn tràn. Các tràn bổ sung. –

0

Không để nitpick, nhưng bạn có nghĩa là "integer overflow" hơn là "tràn bộ nhớ đệm".

Tôi không biết C#, do đó có thể là một cách khác, nhưng bạn có thể bắt chước một sự thay đổi unsigned bằng cách chỉ che đi các bit đầu: (x >> 1) & 0x80000000

+0

có, tôi có nghĩa là tràn số nguyên – Paco

2

Bạn có thể làm điều đó đây cách:

x = largeValue1; 
    y = largeValue2; 
    return (x&y)+((x^y)/2); 

Đó là cách khá đơn giản để có được trung bình hai số nguyên không bị tràn.

Nếu bạn muốn, bạn có thể thay thế phân chia theo hai lần bằng một chút thay đổi, nhưng trình biên dịch sẽ làm điều đó cho bạn dù sao.

3
int alwaysPositive = (largeValue1 >> 1) + (largeValue2 >> 1) + (largeValue1 & largeValue2 & 0x01); 

Ý tưởng đằng sau ở trên là nếu bạn chia trước kết quả trước khi thêm, thì bạn sẽ tránh tràn vì cả hai bit thứ tự cao sẽ không được đặt. Sau đó, bạn thêm một số logic chỉnh sửa nhỏ để tăng giá trị của một nếu cả hai đều dương (làm tròn xuống). Nếu bạn chỉ quan tâm nếu một trong hai kết quả dương tính (làm tròn) thì bạn có thể thay đổi nó để

int alwaysPositive = (largeValue1 >> 1) + (largeValue2 >> 1) + ((largeValue1 | largeValue2) & 0x01); 
0
try 
{ 
    checked { alwaysPositive3 = (largeValue1 + largeValue2); } 
} 
catch (OverflowException ex) 
{ 
    // Corrective logic 
} 
+0

Bạn sẽ điền vào cho logic điều chỉnh ở đây? – Paco

+0

cũng có, nếu điều này là trong một vòng lặp bên trong của một thuật toán nó thực sự có thể làm chậm nó xuống – henon

2

unchecked((largeValue1 + largeValue2) >> 1) là một tùy chọn.

Xem tài liệu cho số unchecked keyword.

+0

Điều đó sẽ chỉ hoạt động nếu bạn đang sử dụng số nguyên unsigned – ilitirit

+0

Tôi không tin rằng công trình này. Tất cả những gì nó làm là loại bỏ việc kiểm tra các cờ mà bạn có vấn đề. Nó không thực sự loại bỏ vấn đề. –

+0

Tôi nghi ngờ có rất nhiều điều chỉ làm việc cho các số nguyên không dấu. CPU thường xử lý các giá trị đã ký giống như đã ký. – Nefzen

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