developer tip

두 정수의 부호가 같은지 확인하는 가장 간단한 방법은 무엇입니까?

copycodes 2020. 12. 2. 21:29
반응형

두 정수의 부호가 같은지 확인하는 가장 간단한 방법은 무엇입니까?


두 정수의 부호가 같은지 확인하는 가장 간단한 방법은 무엇입니까? 이 작업을 수행하는 짧은 비트 트릭이 있습니까?


다음은 정수 크기에 의존하지 않거나 오버플로 문제가있는 C / C ++에서 작동하는 버전입니다 (예 : x * y> = 0이 작동하지 않음).

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

물론 괴짜와 템플릿을 사용할 수 있습니다.

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

참고 : 배타적 or를 사용하고 있으므로 부호가 같을 때 LHS와 RHS가 다르기 때문에 0에 대해 다른 검사를 수행해야합니다.


뭐가 잘못 됐어

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

?


(a ^ b) >= 0

부호가 같으면 1, 그렇지 않으면 0으로 평가됩니다.


정수의 부호를 결정하는 비트 트릭에 대해주의해야합니다. 그런 다음 해당 숫자가 내부적으로 어떻게 표현되는지에 대해 가정해야하기 때문입니다.

거의 100 %의 경우 정수는 2의 칭찬 으로 저장 되지만 특정 저장 형식을 보장하는 데이터 유형을 사용하지 않는 한 시스템 내부에 대해 가정하는 것은 좋지 않습니다.

2의 칭찬에서 정수의 마지막 (가장 왼쪽) 비트를 확인하여 음수인지 확인할 수 있으므로이 두 비트 만 비교할 수 있습니다. 이것은 0이 양수와 동일한 부호를 가질 것이라는 것을 의미하며, 이는 대부분의 언어에서 구현 된 부호 함수와 상충됩니다.

개인적으로 저는 당신이 선택한 언어의 기호 기능을 사용하고 싶습니다. 이와 같은 계산에 성능 문제가있을 가능성은 거의 없습니다.


32 비트 정수 가정 :

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

약간 더 간결 :

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

"비트 트릭"과 "가장 단순"이 동의어라고 생각할지 모르겠습니다. 나는 (비록 32 비트 정수에 서명 가정합니다 답변을 많이 볼 서명을 요청하는 바보를); 부동 소수점 값에 적용되는지 확실하지 않습니다.

"가장 간단한"검사는 두 값이 0과 비교되는 방식을 비교하는 것 같습니다. 유형을 비교할 수 있다고 가정하면 매우 일반적입니다.

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

표시가 반대이면 거짓입니다. 징후가 같으면 사실입니다.


(integer1 * integer2)> 0

두 정수가 부호를 공유 할 때 곱셈의 결과는 항상 양수이기 때문입니다.

어떤 경우에도 0을 동일한 부호로 취급하려면> = 0으로 만들 수도 있습니다.


2가 산술을 보완한다고 가정합니다 ( http://en.wikipedia.org/wiki/Two_complement ) :

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

최적화 된 최신 프로세서에서는 최소 2 개의 명령어와 1ns 미만이 소요될 수 있습니다.

2가 산술을 보완한다고 가정하지 않습니다.

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

이것은 하나 또는 두 개의 추가 지침이 필요할 수 있으며 조금 더 오래 걸릴 수 있습니다.

곱셈을 사용하는 것은 오버플로에 취약하기 때문에 나쁜 생각입니다.


만약 (x * y)> 0 ...

0이 아닌 것으로 가정합니다.


기술적 인 측면에서 보면, 현대적인 아키텍처에서도 조금 뒤틀린 솔루션이 곱셈보다 훨씬 더 효율적일 것입니다. 당신이 절약하는 것은 약 3주기 뿐이지 만 "페니 절약"에 대해 그들이 말하는 것을 알고 있습니다 ...


내 머리 꼭대기에서 ...

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

분기없는 C 버전 :

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

정수 유형에 대한 C ++ 템플릿 :

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

2의 보수 산술을 사용하는 모든 int 크기의 경우 :

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

32 비트 가정

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

... the answer if(x*y>0) is bad due to overflow


if (a*b < 0) sign is different, else sign is the same (or a or b is zero)


Thinking back to my university days, in most machine representations, isn't the left-most bit of a integer a 1 when the number is negative, and 0 when it's positive?

I imagine this is rather machine-dependent, though.


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

if ( same_sign ) ... else ...


Better way using std::signbit as follows:

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

It also support other basic types (double, float, char etc).

참고URL : https://stackoverflow.com/questions/66882/simplest-way-to-check-if-two-integers-have-same-sign

반응형