转载自github
awesome-bits
A curated list of awesome bitwise operations and tricks
Maintainer - Keon Kim
Please feel free to pull requests
Integers
Set nth bit
1 | x | (1<<n) |
Unset nth bit
1
x & ~(1<<n)
Toggle nth bit
1 | x ^ (1<<n) |
Round up to the next power of two
1 | unsigned int v; //only works if v is 32 bit |
Get the maximum integer
1 | int maxInt = ~(1 << 31); |
Get the minimum integer
1 | int minInt = 1 << 31; |
Get the maximum long
1 | long maxLong = ((long)1 << 127) - 1; |
Multiply by 2
1 | n << 1; // n*2 |
Divide by 2
1 | n >> 1; // n/2 |
Multiply by the mth power of 2
1 | n << m; |
Divide by the mth power of 2
1 | n >> m; |
Check Equality
This is 35% faster in Javascript
1 | (a^b) == 0; // a == b |
Check if a number is odd
1 | (n & 1) == 1; |
Exchange (swap) two values
1 | //version 1 |
Get the absolute value
1 | //version 1 |
Get the max of two values
1 | b & ((a-b) >> 31) | a & (~(a-b) >> 31); |
Get the min of two values
1 | a & ((a-b) >> 31) | b & (~(a-b) >> 31); |
Check whether both numbers have the same sign
1 | (x ^ y) >= 0; |
Flip the sign
1 | i = ~i + 1; // or |
Calculate 2n
1 | 1 << n; |
Whether a number is power of 2
1 | n > 0 && (n & (n - 1)) == 0; |
Modulo 2n against m
1 | m & ((1 << n) - 1); |
Get the average
1 | (x + y) >> 1; |
Get the mth bit of n (from low to high)
1 | (n >> (m-1)) & 1; |
Set the mth bit of n to 0 (from low to high)
1 | n & ~(1 << (m-1)); |
Check if nth bit is set
1 | if (x & (1<<n)) { |
Isolate (extract) the right-most 1 bit
1 | x & (-x) |
Isolate (extract) the right-most 0 bit
1 | ~x & (x+1) |
Set the right-most 0 bit to 1
1 | x | (x+1) |
Set the right-most 1 bit to 0
1 | x & (x-1) |
n + 1
1 | -~n |
n - 1
1 | ~-n |
Get the negative value of a number
1 | ~n + 1; |
if (x == a) x = b; if (x == b) x = a;
1 | x = a ^ b ^ x; |
Swap Adjacent bits
1 | ((n & 10101010) >> 1) | ((n & 01010101) << 1) |
Different rightmost bit of numbers m & n
1 | (n^m)&-(n^m) // returns 2^x where x is the position of the different bit (0 based) |
Common rightmost bit of numbers m & n
1 | ~(n^m)&(n^m)+1 // returns 2^x where x is the position of the common bit (0 based) |
Floats
These are techniques inspired by the fast inverse square root method. Most of these
are original.
Turn a float into a bit-array (unsigned uint32_t)
1 |
|
Caveat: Type pruning via unions is undefined in C++; use std::memcpy
instead.
Turn a bit-array back into a float
1 | float i2f(uint32_t x) { |
Approximate the bit-array of a positive float using frexp
frexp
gives the 2n decomposition of a number, so that man, exp = frexp(x)
means that man * 2exp = x and 0.5 <= man < 1.
1 | man, exp = frexp(x); |
Caveat: This will have at most 2-16 relative error, since man + 125 clobbers the last 8 bits, saving the first 16 bits of your mantissa.
Fast Inverse Square Root
1 | return i2f(0x5f3759df - f2i(x) / 2); |
Caveat: We’re using the i2f
and the f2i
functions from above instead.
See this Wikipedia article for reference.
Fast nth Root of positive numbers via Infinite Series
1 | float root(float x, int n) { |
See this blog post regarding the derivation.
Fast Arbitrary Power
1 | return i2f((1 - exp) * (0x3f800000 - 0x5c416) + f2i(x) * exp) |
Caveat: The 0x5c416
bias is given to center the method. If you plug in exp = -0.5, this gives the 0x5f3759df
magic constant of the fast inverse root method.
See these set of slides for a derivation of this method.
Fast Geometric Mean
The geometric mean of a set of n
numbers is the nth root of their
product.
1 |
|
See here for its derivation.
Fast Natural Logarithm
1 | #DEFINE EPSILON 1.1920928955078125e-07 |
Caveat: The bias term of 0x66774
is meant to center the method. We multiply by ln(2)
at the end because the rest of the method computes the log2(x)
function.
See here for its derivation.
Fast Natural Exp
1 | return i2f(0x3f800000 + (uint32_t)(x * (0x800000 + 0x38aa22))) |
Caveat: The bias term of 0x38aa22
here corresponds to a multiplicative scaling of the base. In particular, it
corresponds to z
such that 2z = e
See here for its derivation.
Strings
Convert letter to lowercase:
1 | OR by space => (x | ' ') |
Convert letter to uppercase:
1 | AND by underline => (x & '_') |
Invert letter’s case:
1 | XOR by space => (x ^ ' ') |
Letter’s position in alphabet:
1 | AND by chr(31)/binary('11111')/(hex('1F') => (x & "\x1F") |
Get letter’s position in alphabet (for Uppercase letters only):
1 | AND by ? => (x & '?') or XOR by @ => (x ^ '@') |
Get letter’s position in alphabet (for lowercase letters only):
1 | XOR by backtick/chr(96)/binary('1100000')/hex('60') => (x ^ '`') |
Miscellaneous
Fast color conversion from R5G5B5 to R8G8B8 pixel format using shifts
1 | R8 = (R5 << 3) | (R5 >> 2) |
Note: using anything other than the English letters will produce garbage results