2010-06-08 43 views
7

Tôi muốn có thể truy cập bit dấu của một số trong C++. mã hiện tại của tôi trông giống như sau:Làm cách nào để truy cập vào bit dấu của một số trong C++?

int sign bit = number >> 31; 

đó dường như làm việc, đem lại cho tôi 0 cho các số dương và -1 cho số âm. Tuy nhiên, tôi không thấy làm thế nào tôi có được -1 cho số âm: nếu 12 là

0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1100 

sau đó -12 là

1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0011 

và chuyển nó 31 bit sẽ làm cho

0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 

đó là 1, không phải -1, vậy tại sao tôi lại nhận được -1 khi tôi thay đổi nó?

+0

thể trùng lặp của (http: // stackoverflow. com/questions/141525/absolute-beginners-to-bit-shifting) – msw

+0

int sign_bit = (int) (số> 0); – aviraldg

+5

Đối với [hai phần bổ sung] (http://en.wikipedia.org/wiki/Two%27s_complement#Complement_of_a_positive_number) (mà hầu hết các hệ thống hiện đại sử dụng), thì -12 của bạn là sai. Nó sẽ kết thúc 0100. –

Trả lời

11

Kết quả của việc dịch chuyển đúng số âm trong C++ được xác định thực hiện. Vì vậy, không ai biết những gì phải chuyển dịch -12 của bạn sẽ nhận được trên nền tảng cụ thể của bạn. Bạn nghĩ rằng nó nên làm cho các bên trên (1), trong khi tôi nói rằng nó có thể dễ dàng tạo ra tất cả các mô hình, đó là -1. Cái sau được gọi là dịch chuyển dấu mở rộng. Trong việc mở rộng ký hiệu, bit dấu hiệu được sao chép sang bên phải, nhưng không bao giờ bị lệch khỏi vị trí của nó.

Nếu tất cả bạn quan tâm là giá trị bit dấu, thì hãy ngừng lãng phí thời gian cố gắng sử dụng các thao tác bitwise, như ca.vv Chỉ cần so sánh số của bạn với 0 và xem liệu nó có âm hay không.

+1

Đây là một bài viết thực sự cũ nhưng tôi chỉ nhìn thấy điều này trong khi tìm kiếm cái gì khác. Tôi thường đồng ý với những gì bạn đang nói ở đây. Nhưng có một số giả định mà ông đã đưa ra trong câu hỏi của ông có thể đã góp phần vào kết quả của mã của ông. Điều này có thể được thực hiện độc lập bằng cách sử dụng bit shifting hoặc chỉ sử dụng một bit-mask để kiểm tra bit dấu. –

+0

Điều này không phân biệt -0.0 từ +0.0. Bạn cần phải truy cập bit đăng nhập cho điều đó. Xem câu trả lời của John. –

+0

@NeilG Dựa trên văn bản trong câu hỏi, có vẻ như tôi đang hỏi về các số nguyên. –

24

Điều này thì sao?

int sign = number < 0;

2

Nhà điều hành >> được thực hiện một arithmetic shift, mà vẫn giữ được dấu của số.

+4

No. Loại toán tử nào được thực hiện bởi toán tử '>>' được định nghĩa thực hiện. Có thể là bất kỳ sự thay đổi nào. – AnT

+0

@AndreyT: Tôi đã nói "toán tử' >> 'đang thực hiện một phép dịch số học", và đó chính xác là những gì nó đang làm trong trường hợp này, dựa trên mô tả của OP. Lưu ý rằng tôi * không * nói "toán tử' >> 'luôn thực hiện phép dịch số học" hoặc bất kỳ thứ gì giống như vậy. Có lẽ tôi nên rõ ràng hơn, nhưng dù sao đi nữa, tôi không nghĩ câu trả lời của tôi xứng đáng là một lời nói xấu. – LukeH

+2

@Downvoters: Hãy biện minh cho chính mình. Tôi giải thích * chính xác * vấn đề của OP là gì. Tôi đã không đưa ra bất kỳ tuyên bố rộng nào như "toán tử' >> 'luôn thực hiện thay đổi số học"; Tôi đã giải thích * chính xác * toán tử '>>' đang làm gì * trong trường hợp cụ thể này *. – LukeH

7

Vì bạn đang chuyển số nguyên đã ký. Truyền số nguyên thành unsigned:

int sign_bit = ((unsigned int)number) >> 31; 
4

Đối với số nguyên, hãy thử number < 0.

Đối với số dấu chấm động, bạn cũng có thể muốn tính đến thực tế là số không có dấu. Tức là, tồn tại một -0.0 khác biệt với +0.0. Để phân biệt hai, bạn muốn sử dụng std::signbit.

1
bool signbit(double x) 
{ 
    return 1.0/x != 1.0/fabs(x); 
} 

Giải pháp của tôi hỗ trợ +/- 0.

2

Bạn có thể sử dụng thư viện cmath

#include <cmath> 

và sử dụng nó như

std::cout << std::signbit(num); 

Chức năng này được một giá trị float như đầu vào và một giá trị bool như đầu ra.

true for negative 
false for positive 

ví dụ

std :: cout < < std :: signbit (1);

sẽ cung cấp cho bạn một 0 như đầu ra (false)

nhưng khi sử dụng chức năng này, bạn phải cẩn thận về zero

std::cout << std::signbit(-0.0); // 512 (true) 
std::cout << std::signbit(+0.0); // 0 (false) 

Sản lượng của dòng này là không giống nhau.

Để loại bỏ vấn đề này, bạn có thể sử dụng:

float x = +0.01; 
std::cout << (x >= 0 ? (x == 0 ? 0 : 1) : -1); 

mà cung cấp cho: [? Hướng dẫn Absolute Beginner để Bit Chuyển]

0 for 0 
1 for positive 
-1 for negative 
-1
bool signbit(double x) 
{ 
    return (__int64)x & 0x8000000000000000LL != 0LL; 
} 

bool signbit(float x) 
{ 
    return (__int32)x & 0x80000000 != 0; 
} 
+0

gây ra hành vi không xác định nếu 'x' nằm ngoài phạm vi' __int64' –

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