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

StackOverflow https://stackoverflow.com/questions/66882

  •  09-06-2019
  •  | 
  •  

문제

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

도움이 되었습니까?

해결책

다음은 정수 크기에 의존하지 않거나 오버플로 문제가 없는 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);
}

메모:우리는 배타적 논리합을 사용하기 때문에 부호가 동일할 때 LHS와 RHS가 다르기를 원하므로 0에 대해 다른 검사를 수행해야 합니다.

다른 팁

무슨 문제 있어?

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

?

(a ^ b) >= 0

부호가 동일하면 1로 평가되고, 그렇지 않으면 0으로 평가됩니다.

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

거의 100%의 경우 정수는 다음과 같이 저장됩니다. 두 사람의 칭찬, 그러나 특정 저장 형식을 보장하는 데이터 유형을 사용하지 않는 한 시스템 내부에 대해 가정하는 것은 좋은 습관이 아닙니다.

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);
}

표시가 반대이면 거짓이 됩니다.표시가 동일하면 사실이 됩니다.

(정수1 * 정수2) > 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)

...대답 if(x*y>0) 오버플로로 인해 불량

(a*b < 0) 부호가 다른 경우, 그렇지 않은 경우 부호는 동일합니다(또는 a 또는 b는 0임).

대학 시절을 되돌아보면 대부분의 기계 표현에서 정수의 가장 왼쪽 비트는 숫자가 음수일 때 1이고 양수일 때 0이 아닌가요?

하지만 나는 이것이 기계에 다소 의존적이라고 생각합니다.

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

if (동일_부호) ...또 다른 ...

더 나은 사용 방법 표준::signbit 다음과 같이:

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

또한 다른 기본 유형도 지원합니다(double, float, char 등).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top