2014-09-17 3 views
0

2^p의 다음 배수를 반환하는 함수를 만들고 싶습니다. 작동하는지2의 다음으로 큰 힘을 반환하기위한 비트 연산

여기 ... 시도,하지만 확실하지입니다 :

#define P 20 
#define ALIGN_FORWARD(x, alignment) ((((int)x) + ((alignment)-1)) & (~((alignment)-1))) 

int round_up(int x) 
{ 
    return ALIGN_FORWARD(x, P); 
} 
+0

왜 실행하고 테스트하여 작동하는지보십시오. – indiv

+2

'2^p'를 다루는 핵심 요소 인'(1 << p)'가 공식에서 누락되어서 그것이 옳지 않다고 확신합니다. [이 페이지] (https://graphics.stanford.edu/~seander/bithacks.html)를 보시면 필요한 것이있을 수 있습니다. – dasblinkenlight

+0

코드를 직선 코드로 테스트하고 테스트 한 다음 매크로로 변환합니다. – lboshuizen

답변

2

이 조각은 먼저 가장 높은 세트 비트 아래의 모든 비트를 채 웁니다. v |= v >> 1 이후 처음 두 비트를 복사 할 수 있습니다. 마지막으로 값이 1 씩 증가합니다. 그렇지 않으면 결과는 항상 0 것이기 때문에 부호 비트가 시프트 조작으로 확장됩니다 때문에

uint32_t v = ...; 
v |= v >> 1; 
v |= v >> 2; 
v |= v >> 4; 
v |= v >> 8; 
v |= v >> 16; 
v += 1; 

uint32_tunsigned 부분은 중요하다. 값이 uint64_t 인 경우 추가 시프트를 추가해야하며 uint16_t 인 경우 교대를 제거해야합니다.

입력이 8 일 경우 결과는 16이됩니다. 원하지 않으면 입력이 2의 거듭 제곱인지 테스트해야합니다. . 당신이 (8 = 0b1000, 7 = 0b111)를 감소,이 가드 사용할 수있는 경우 2의 거듭 제곱의 이진 표현이 하나 개의 문자 짧은 것을 알고 : https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2에서

if ((v & (v - 1)) > 0) { 
    … 
} 

(메모리에서 재현 원본을, 더 많은 흥미로운 트릭이 포함되어 있습니다.)