모듈러스 연산자 대신 비트 단위


91

예를 들어 2의 거듭 제곱 모듈로가 다음과 같이 표현 될 수 있음을 알고 있습니다.

  x % 2 inpower n == x & (2 inpower n - 1).

예 :

x % 2 == x & 1
x % 4 == x & 3
x % 8 == x & 7 

두 수의 일반 비 제곱은 어떻습니까?

의 말을하자:

x % 7 ==?


8
@Neil-Modulo 및 Binary 그리고 매우 기본적인 작업이므로 모든 컴퓨터 언어에서 거의 동일하다고 생각합니다.
제임스 Kolpack

1
게시 된 언어를 보지 못하는 것이 조금
지겹습니다

1
이것을 이해하는 데 어려움을 겪는 사람을 위해 stackoverflow.com/a/13784820/1414639를 살펴보십시오 . 아, 그리고 V8의 JS에서 비트 연산자를 사용하여 성능이 약간 향상되었습니다.
Bardi Harbourow

1
@JamesKolpack 비트 연산은 모듈로보다 CPU에서 훨씬 빠르게 수행 할 수 있습니다. 실제로 레지스터를 0으로 만드는 일반적인 어셈블리 트릭은 (이 사실 때문에) 레지스터를 XOR하는 것입니다. 요즘 컴파일러는 2의 거듭 제곱의 모듈로를 최적화 할 수 있지만 모르겠습니다
Kaiser Keister

답변:


70

우선, 실제로 그렇게 말하는 것은 정확하지 않습니다.

x % 2 == x & 1

간단한 반례 : x = -1. Java를 포함한 많은 언어에서 -1 % 2 == -1. 즉, %반드시 모듈로의 전통적인 수학적 정의는 아닙니다. 예를 들어 Java는이를 "나머지 연산자"라고 부릅니다.

비트 최적화와 관련하여, 2의 모듈로 거듭 제곱 만이 비트 산술에서 "쉽게"수행 될 수 있습니다. 일반적으로 말하면, b 의 모듈로 거듭 제곱 만이 b 의 숫자 표현으로 "쉽게"수행 될 수 있습니다.

예를 들어, 10 진법에서 음수 가 아닌 N경우 N mod 10^k는 최하위 k숫자 만 사용합니다.

참고 문헌


1
-1 = -1 (mod 2), 무엇을 얻고 있는지 잘 모르겠습니다 . IEEE 754 나머지 와 동일하지 않다는 의미 입니까?
BlueRaja-Danny Pflughoeft

2
@BlueRaja : mod 2에서 -1에 대한 공통 잔류 물은 1입니다. en.wikipedia.org/wiki/Modular_arithmetic#Remainders
polygenelubricants

@BlueRaja : 음수를 허용하는 경우 기본적으로 확신 할 수있는 것은 (특히 언어가 언급되지 않았기 때문에) (a / b) / b + a % b == aC 형 연산자의 경우 a와 b 정수, b가 0이 아니고 abs(a % b) < abs(b)동일한 조항이있는 것입니다.
David Thornley

1
@DavidThornley-당신이 의미한다고 가정합니다 (a / b)* b + a % b == a.
sfjac 2014-06-19

40

간단한 방법 만 비트를 사용하여 2 ^ 난 숫자의 모듈을 찾을 수는.

n % 3, n % 7과 같은 링크에 따라 Mersenne 사례 를 해결하는 독창적 인 방법 이 있습니다. n % 5, n % 255 및 n % 6과 같은 복합 사례에 대한 특수 사례가 있습니다.

경우 2 ^ i, (2, 4, 8, 16 ...)

n % 2^i = n & (2^i - 1)

더 복잡한 것은 설명하기 어렵습니다. 호기심이 많은 경우에만 읽으십시오.


1
vote ++; 훌륭한 링크, 참조 주셔서 감사합니다. 나는 다른 사람들에게 살펴 보라고 조언합니다. 조금 복잡하더라도 읽을만한 가치가 있습니다.
varzeak

링크는 대답의 가장 좋은 부분입니다.
Amit Kumar

% N = 2 ^ N 및 I (1 << I - 1)
카르 틱 싱

18

이진 표현에서 1 비트 만 '1'로 설정되는 고유 한 속성을 갖기 때문에 2의 거듭 제곱 (그리고 종종 양의 값만)에 대해서만 작동합니다. 다른 숫자 클래스는이 속성을 공유하지 않기 때문에 대부분의 모듈러스 식에 대해 비트 및 식을 만들 수 없습니다.


2
삼항 아키텍처에서 작동하는 경우 상황이 약간 변경됩니다. 그러나 가능성은 거의 없습니다.
Noldorin 2010-06-18

나는 당신이 표현하는 방식이 마음에
듭니다

12

이것은 컴퓨터가 2 진법의 숫자를 나타 내기 때문에 특별히 특별한 경우입니다. 이것은 일반화 가능합니다.

(숫자) base % base x

(number) base 의 마지막 x 자리와 동일 합니다 .


5

효율적인 알고리즘이 존재하는 2의 거듭 제곱 이외의 모듈 리가 있습니다.

예를 들어 x가 32 비트 unsigned int이면 x % 3 = popcnt (x & 0x55555555)-popcnt (x & 0xaaaaaaaa)


4

"%"연산자가없는 모듈로 "7"

int a = x % 7;

int a = (x + x / 7) & 7;

3
10 % 2 = 0에서는 작동하지 않습니다. (10 + 10/2) & 2 = 15 & 2 = 2, 비슷하게 10 % 6 = 4. (10 + 10/6) & 6 = 11 & 6 = 2
스리 람 무랄리

10
또한 모듈로 사용을 피하고 싶을 때 왜 나누기를 원합니까? AFAIK, 나누는 명령은 나머지를 얻는 명령과 동일합니다.
Horse SMith

2
@SriramMurali 짝수 모드를 사용했기 때문에 물론 작동하지 않을 것입니다. 이것은 OP가 말한 것처럼 이상한 해결책입니다 .
ylun.ca 2015-08-11

3

&바이너리에서 비트 및 ( ) 연산자를 사용하지 않습니다. 증거 스케치 :

, 그러나 k! = 2 ^ n-1 과 같은 값 k 가 있다고 가정 합니다. 그러면 x == k 이면 표현식 이 "올바르게 작동" 하는 것처럼 보이고 결과는 k 입니다. 이제 x == ki를 고려하십시오 . k에 "0"비트가있는 경우 0보다 큰 i 가 있으며 ki 는 해당 위치에서 1 비트로 만 표현 될 수 있습니다. (예 : 1011 (11)은 100 (4)를 빼면 0111 (7)이되어야하며,이 경우 000 비트는 i = 4 일 때 100이됩니다 .) k 의 식에서 비트 가 0에서 변경되어야하는 경우 기를 나타내는 사람에게x & k == x % (k + 1)x & k, 그러면 x % (k + 1)을 올바르게 계산할 수 없습니다 .이 경우 ki 여야 하지만 비트 부울을 사용하여 마스크가 주어진 값을 생성 할 방법이 없습니다.


2

이 특정 경우 (mod 7)에서도 % 7을 비트 연산자로 대체 할 수 있습니다.

// Return X%7 for X >= 0.
int mod7(int x)
{
  while (x > 7) x = (x&7) + (x>>3);
  return (x == 7)?0:x;
}

8 % 7 = 1이기 때문에 작동합니다. 분명히이 코드는 단순한 x % 7보다 효율성이 떨어지고 읽기도 어렵습니다.


1

bitwise_and, bitwise_or 및 bitwise_not을 사용하면 모든 비트 구성을 다른 비트 구성으로 수정할 수 있습니다 (즉, 이러한 연산자 집합은 "기능적으로 완전"임). 그러나 모듈러스와 같은 연산의 경우 일반 공식은 필연적으로 매우 복잡 할 것입니다. 나는 그것을 재현하려고 시도조차하지 않을 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.