개발자가 알아야 할 유용한 비트 연산자 코드 트릭은 무엇입니까?
비트 연산자를 사용할 이유가 없다고 말해야하지만, 더 효율적으로 수행 할 수있는 몇 가지 작업이 있다고 확신합니다. "이동"및 "OR-ing"이 문제를보다 효율적으로 해결하는 데 어떻게 도움이 되었습니까?
유명한 Bit Twiddling Hacks보기
대부분의 곱하기 / 나누기 작업은 불필요합니다. 컴파일러가 자동으로이를 수행하므로 사람들을 혼란스럽게 할 것입니다.
그러나 하드웨어 또는 통신 프로토콜로 작업하는 경우 매우 유용한 '확인 / 설정 / 토글 비트 N'유형의 해킹이 많이 있습니다.
문자열 (문자)에 비트 연산 사용
문자를 소문자 로 변환 :
OR
공간 별 =>(x | ' ')
- 문자가 이미 소문자 인 경우에도 결과는 항상 소문자입니다.
- 예.
('a' | ' ') => 'a'
;('A' | ' ') => 'a'
문자를 대문자로 변환 :
AND
밑줄로 =>(x & '_')
- 결과는 문자가 이미 대문자 인 경우에도 항상 대문자입니다.
- 예.
('a' & '_') => 'A'
;('A' & '_') => 'A'
대소 문자 반전 :
XOR
공간 별 =>(x ^ ' ')
- 예.
('a' ^ ' ') => 'A'
;('A' ^ ' ') => 'a'
알파벳에서 글자의 위치 :
AND
작성자chr(31)
/binary('11111')
/ (hex('1F')
=>(x & "\x1F")
- 결과는 1..26 범위이며 대소 문자는 중요하지 않습니다.
- 예.
('a' & "\x1F") => 1
;('B' & "\x1F") => 2
편지의 가져 오기 위치를 알파벳 (대한 대문자 문자 만) :
AND
의하여?
=>(x & '?')
또는XOR
의해@
=>(x ^ '@')
- 예.
('C' & '?') => 3
;('Z' ^ '@') => 26
편지의 가져 오기 위치를 알파벳 (대한 소문자 문자 만) :
XOR
백틱 /chr(96)
/binary('1100000')
/hex('60')
=>(x ^ '`')
- 예.
('d' ^ '`') => 4
;('x' ^ '`') => 25
참고 : 영어 이외의 문자를 사용하면 쓰레기 결과가 생성됩니다.
- 정수에 대한 비트 연산 (int)
최대 정수 얻기
int maxInt = ~(1 << 31);
int maxInt = (1 << 31) - 1;
int maxInt = (1 << -1) - 1;
최소 정수 얻기
int minInt = 1 << 31;
int minInt = 1 << -1;
최대 길이를 얻으십시오
long maxLong = ((long)1 << 127) - 1;
2 곱하기
n << 1; // n*2
2로 나눈
n >> 1; // n/2
2의 m 제곱을 곱합니다.
n << m;
2의 m 제곱으로 나눈 값
n >> m;
홀수 확인
(n & 1) == 1;
두 값 교환
a ^= b;
b ^= a;
a ^= b;
절대 값 얻기
(n ^ (n >> 31)) - (n >> 31);
두 값의 최대 값 얻기
b & ((a-b) >> 31) | a & (~(a-b) >> 31);
두 값의 최소값 얻기
a & ((a-b) >> 31) | b & (~(a-b) >> 31);
둘 다 같은 부호가 있는지 확인하십시오
(x ^ y) >= 0;
2 ^ n 계산
2 << (n-1);
계승 2인지 여부
n > 0 ? (n & (n - 1)) == 0 : false;
m에 대한 모듈로 2 ^ n
m & (n - 1);
평균을 얻으십시오
(x + y) >> 1;
((x ^ y) >> 1) + (x & y);
n의 m 번째 비트를 가져옵니다 (낮은 값에서 높은 값으로)
(n >> (m-1)) & 1;
n의 m 번째 비트를 0으로 설정 (낮음에서 높음으로)
n & ~(1 << (m-1));
n + 1
-~n
n-1
~-n
대비 번호 얻기
~n + 1;
(n ^ -1) + 1;
만약 (x == a) x = b; 만약 (x == b) x = a;
x = a ^ b ^ x;
내가 어떤 주파수로 사용해 본 것은 세 가지뿐입니다.
비트 설정 : a | = 1 << bit;
Clear a bit: a &= ~(1 << bit);
Test that a bit is set: a & (1 << bit);
Matters Computational: Ideas, Algorithms, Source Code, by Jorg Arndt (PDF). This book contains tons of stuff, I found it via a link at http://www.hackersdelight.org/
Average without overflow
A routine for the computation of the average (x + y)/2 of two arguments x and y is
static inline ulong average(ulong x, ulong y) // Return floor( (x+y)/2 ) // Use: x+y == ((x&y)<<1) + (x^y) // that is: sum == carries + sum_without_carries { return (x & y) + ((x ^ y) >> 1); }
You can compress data, e.g. a collection of integers:
- See which integer values appear more frequently in the collection
- Use short bit-sequences to represent the values which appear more frequently (and longer bit-sequences to represent the values which appear less frequently)
- Concatenate the bits-sequences: so for example, the first 3 bits in the resulting bit stream might represent one integer, then the next 9 bits another integer, etc.
1) Divide/Multiply by a power of 2
foo >>= x;
(divide by power of 2)
foo <<= x;
(multiply by power of 2)
2) Swap
x ^= y;
y = x ^ y;
x ^= y;
I used bitwise operators to efficiently implement distance calculations for bitstrings. In my application bitstrings were used to represent positions in a discretised space (an octree, if you're interested, encoded with Morton ordering). The distance calculations were needed to know whether points on the grid fell within a particular radius.
Counting set bits, finding lowest/highest set bit, finding nth-from-top/bottom set bit and others can be useful, and it's worth looking at the bit-twiddling hacks site.
That said, this kind of thing isn't day-to-day important. Useful to have a library, but even then the most common uses are indirect (e.g. using a bitset container). Also, ideally, these would be standard library functions - a lot of them are better handled using specialise CPU instructions on some platforms.
While multiplying/dividing by shifting seems nifty, the only thing I needed once in a while was compressing booleans into bits. For that you need bitwise AND/OR, and probably bit shifting/inversion.
I wanted a function to round numbers to the next highest power of two, so I visited the Bit Twiddling website that's been brought up several times and came up with this:
i--;
i |= i >> 1;
i |= i >> 2;
i |= i >> 4;
i |= i >> 8;
i |= i >> 16;
i++;
I use it on a size_t
type. It probably won't play well on signed types. If you're worried about portability to platforms with different sized types, sprinkle your code with #if SIZE_MAX >= (number)
directives in appropriate places.
'Development Tip' 카테고리의 다른 글
프로토 타입 array.last ()에 해당하는 jQuery (0) | 2020.11.25 |
---|---|
Does this function have explicit return values on all control paths? (0) | 2020.11.25 |
어댑터에서 활동을 시작하는 방법은 무엇입니까? (0) | 2020.11.25 |
preg_match를 사용하여 YouTube 동영상 ID 구문 분석 (0) | 2020.11.25 |
import sun.misc.BASE64Encoder 결과 Eclipse에서 컴파일 오류 발생 (0) | 2020.11.25 |