it-swarm-vi.tech

Cách đơn giản nhất để kiểm tra xem hai số nguyên có cùng dấu không?

Cách đơn giản nhất để kiểm tra xem hai số nguyên có cùng dấu không? Có bất kỳ thủ thuật bitwise ngắn để làm điều này?

60
Gerber

Đây là phiên bản hoạt động trong C/C++ không dựa vào kích thước số nguyên hoặc có vấn đề tràn (tức là x * y> = 0 không hoạt động)

bool SameSign(int x, int y)
{
    return (x >= 0) ^ (y < 0);
}

Tất nhiên, bạn có thể tìm hiểu và mẫu:

template <typename valueType>
bool SameSign(typename valueType x, typename valueType y)
{
    return (x >= 0) ^ (y < 0);
}

Lưu ý: Vì chúng tôi đang sử dụng độc quyền hoặc, chúng tôi muốn LHS và RHS khác nhau khi các dấu hiệu giống nhau, do đó kiểm tra khác nhau so với không.

47
Torlack

Có chuyện gì với

return ((x<0) == (y<0));  

?

203
Rik
(a ^ b) >= 0

sẽ đánh giá thành 1 nếu dấu giống nhau, 0 nếu không.

23
Chris Jobson

Tôi sẽ cảnh giác với bất kỳ thủ thuật bitwise nào để xác định dấu của số nguyên, vì khi đó bạn phải đưa ra các giả định về cách các số đó được thể hiện trong nội bộ.

Gần như 100% thời gian, các số nguyên sẽ được lưu trữ dưới dạng hai lời khen , nhưng sẽ không thực tế khi đưa ra các giả định về các phần bên trong của hệ thống trừ khi bạn đang sử dụng một kiểu dữ liệu đảm bảo định dạng lưu trữ cụ thể.

Trong lời khen của hai người, bạn chỉ cần kiểm tra bit cuối cùng (ngoài cùng bên trái) trong số nguyên để xác định xem nó có âm hay không, vì vậy bạn có thể so sánh chỉ hai bit này. Điều này có nghĩa là 0 sẽ có cùng dấu với một số dương, điều này mâu thuẫn với chức năng ký hiệu được triển khai trong hầu hết các ngôn ngữ.

Cá nhân, tôi chỉ sử dụng chức năng ký hiệu của ngôn ngữ bạn đã chọn. Không có khả năng sẽ có bất kỳ vấn đề hiệu suất nào với một phép tính như thế này.

12
SpoonMeiser

Giả sử int 32 bit:

bool same = ((x ^ y) >> 31) != 1;

Hơi ngắn gọn hơn:

bool same = !((x ^ y) >> 31);
6
Patrick

Tôi không thực sự chắc chắn rằng tôi coi "thủ thuật bitwise" và "đơn giản nhất" là đồng nghĩa. Tôi thấy rất nhiều câu trả lời giả định rằng các số nguyên 32 bit đã ký (mặc dù nó would thật ngớ ngẩn khi yêu cầu không dấu); Tôi không chắc chắn họ sẽ áp dụng cho các giá trị dấu phẩy động.

Có vẻ như kiểm tra "đơn giản nhất" sẽ là so sánh cách cả hai giá trị so với 0; điều này khá chung chung giả sử các loại có thể được so sánh:

bool compare(T left, T right)
{
    return (left < 0) == (right < 0);
}

Nếu các dấu hiệu ngược lại, bạn nhận được sai. Nếu các dấu hiệu là như nhau, bạn nhận được đúng.

5
OwenP

(số nguyên 1 * số nguyên)> 0

Bởi vì khi hai số nguyên chia sẻ một dấu, kết quả của phép nhân sẽ luôn dương.

Bạn cũng có thể làm cho nó> = 0 nếu bạn muốn coi 0 là cùng một dấu hiệu cho dù thế nào đi chăng nữa.

4
Benjamin Autin

Giả sử twos bổ sung số học ( http://en.wikipedia.org/wiki/Two_compuity ):

inline bool same_sign(int x, int y) {
    return (x^y) >= 0;
}

Điều này có thể mất ít nhất hai hướng dẫn và ít hơn 1ns trên bộ xử lý hiện đại với tối ưu hóa.

Không giả sử twos bổ sung số học:

inline bool same_sign(int x, int y) {
    return (x<0) == (y<0);
}

Điều này có thể yêu cầu một hoặc hai hướng dẫn thêm và mất nhiều thời gian hơn.

Sử dụng phép nhân là một ý tưởng tồi vì nó dễ bị tràn.

4
user10315

nếu (x * y)> 0 ...

giả sử khác không và như vậy.

3
Yes - that Jake.

Như một lưu ý kỹ thuật, các giải pháp bit-twiddly sẽ hiệu quả hơn nhiều so với nhân, ngay cả trên các kiến ​​trúc hiện đại. Đó chỉ là khoảng 3 chu kỳ mà bạn đang tiết kiệm, nhưng bạn biết họ nói gì về "một xu tiết kiệm" ...

2
Daniel Spiewak

phiên bản C không phân nhánh:

int sameSign(int a, int b) {
    return ~(a^b) & (1<<(sizeof(int)*8-1));
}

Mẫu C++ cho các kiểu số nguyên:

template <typename T> T sameSign(T a, T b) {
    return ~(a^b) & (1<<(sizeof(T)*8-1));
}
1
CAFxX

Chỉ cần ra khỏi đỉnh đầu của tôi ...

int mask = 1 << 31;
(a & mask) ^ (b & mask) < 0;
1
Daniel Spiewak

Đối với bất kỳ kích thước nào của int với số học bổ sung của hai:

#define SIGNBIT (~((unsigned int)-1 >> 1))
if ((x & SIGNBIT) == (y & SIGNBIT))
    // signs are the same
1
Mark Ransom

giả sử 32 bit

if(((x^y) & 0x80000000) == 0)

... câu trả lời if(x*y>0) là xấu do tràn

1
ugasoft

nếu dấu (a * b <0) khác, dấu khác là giống nhau (hoặc a hoặc b bằng 0)

0
dogfish

Nghĩ lại thời đại học của tôi, trong hầu hết các biểu diễn máy, không phải là phần lớn nhất của số nguyên a 1 khi số âm và 0 khi số dương?

Tôi tưởng tượng điều này là khá phụ thuộc vào máy, mặc dù.

0
Dana

int same_sign =! ((x >> 31) ^ (y >> 31));

nếu (same_sign) ... khác ...

0
andrew

Cách tốt hơn bằng cách sử dụng std :: signbit như sau:

std::signbit(firstNumber) == std::signbit(secondNumber);

Nó cũng hỗ trợ các loại cơ bản khác (double, float, char etc).

0
ashiquzzaman33