▶ 计算 unsigned int v 的以 2 为底的对数,结果放入 unsigned int r 。

 // 方法零
#pragma unroll
for(r=;v; r++, v >>= ); // 方法一
union { unsigned int u[]; double d; } t;
t.u[__FLOAT_WORD_ORDER == LITTLE_ENDIAN] = 0x43300000;
t.u[__FLOAT_WORD_ORDER != LITTLE_ENDIAN] = v;
t.d -= 4503599627370496.0;
r = (t.u[__FLOAT_WORD_ORDER == LITTLE_ENDIAN] >> ) - 0x3FF;
// 我的电脑使用的是小端法存储,即 __FLOAT_WORD_ORDER == LITTLE_ENDIAN // 方法二
#define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n static const char LogTable256[] =
{
-, , , , , , , , , , , , , , , ,
LT(), LT(), LT(), LT(), LT(), LT(), LT(),
LT(), LT(), LT(), LT(), LT(), LT(), LT(), LT()
};
register unsigned int t, tt;
if (tt = v >> )
r = (t = tt >> ) ? + LogTable256[t] : + LogTable256[tt];
else
r = (t = v >> ) ? + LogTable256[t] : LogTable256[v]; // 等价的初始化 LogTable256 的方法
LogTable256[] = LogTable256[] = ;
for (int i = ; i < ; i++)
LogTable256[i] = + LogTable256[i / ];
LogTable256[] = -; // 额外规定 log(0) = -1,可以不要 // 等价的 r 的计算方法
if (tt = v >> )
r = + LogTable256[tt];
else if (tt = v >> )
r = + LogTable256[tt];
else if (tt = v >> )
r = + LogTable256[tt];
else
r = LogTable256[v]; // 方法三
const unsigned int b[] = { 0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000 };
const unsigned int S[] = { , , , , };
register unsigned int r = ;
for (int i = ; i >= ; i--)
{
if (v & b[i])
{
v >>= S[i];
r |= S[i];
}
} // 等价的 r 的计算方法
register unsigned int shift;
r = (v > 0xFFFF) << ; v >>= r;
shift = (v > 0xFF) << ; v >>= shift; r |= shift;
shift = (v > 0xF) << ; v >>= shift; r |= shift;
shift = (v > 0x3) << ; v >>= shift; r |= shift;
r |= (v >> ); // 方法四,已知 v 是 2 的整数次幂
static const unsigned int b[] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 };
register unsigned int r = (v & b[]) != ;
#pragma unroll
for (i = ; i > ; i--)
r |= ((v & b[i]) != ) << i; // 方法五
static const int MultiplyDeBruijnBitPosition[] =
{
, , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , ,
};
v |= v >> ;
v |= v >> ;
v |= v >> ;
v |= v >> ;
v |= v >> ;
r = MultiplyDeBruijnBitPosition[(uint32_t)(v * 0x07C4ACDDU) >> ]; // 方法六,已知 v 是 2 的整数次幂
static const int MultiplyDeBruijnBitPosition2[] =
{
, , , , , , , , , , , , , , , ,
, , , , , , , , , , , , , , ,
};
r = MultiplyDeBruijnBitPosition2[(uint32_t)(v * 0x077CB531U) >> ];

▶ 计算 unsigned int v 的以 10 为底的对数,结果放入 int r 。

 // 方法一
int t;
static unsigned int const PowersOf10[] = { , , , , , ,, , , };
t = (IntegerLogBase2(v) + ) * >> ;// 使用前面的方法计算以 2 为底的对数
r = t - (v < PowersOf10[t]); // 方法二
r = (v >= ) ? : (v >= ) ? : (v >= ) ? :
(v >= ) ? : (v >= ) ? : (v >= ) ? :
(v >= ) ? : (v >= ) ? : (v >= ) ? : ;

▶ 计算 float v 的以 2 为底的对数,结果放入 int r 。

 // 方法一
r = *(const int *)&v;// 等价于 memcpy(&r, &v, sizeof r);
r = (r >> ) - ; // 稳定性改进,需要用到求 2 为底的对数方法里的 LogTable256
int x = *(const int *)&v;
c = x >> ;
if (c) // 正常浮点
c -= ;
else
{ // 非正常浮点,c = intlog2(x) - 149;
register unsigned int t;
if (t = x >> )
c = LogTable256[t] - ;
else
c = (t = x >> ) ? LogTable256[t] - : LogTable256[x] - ;
}

▶ 计算 float v 的 21/r 次幂的以 2 为底的对数(int r),结果放入 int c。

 // 方法一
c = *(const int *)&v;
c = ((((c - 0x3f800000) >> r) + 0x3f800000) >> ) - ;

▶ 计算 unsigned int v 的二进制表示中右侧连续的 0 的个数

 // 方法零
for (c = ; v > && v & == ; c++, v >>= ); // 方法一
if (v)
{
v = (v ^ (v - )) >> ;
for (c = ; v; c++)
v >>= ;
}
else
c = CHAR_BIT * sizeof(v); // 方法二
c=;
v &= -signed(v);
if (v) c--;
if (v & 0x0000FFFF) c -= ;
if (v & 0x00FF00FF) c -= ;
if (v & 0x0F0F0F0F) c -= ;
if (v & 0x33333333) c -= ;
if (v & 0x55555555) c -= ; // 方法三,注意当 v == 0 时 c = 31
if (v & 0x1)
c = ;
else
{
c = ;
if ((v & 0xffff) == )
{
v >>= ;
c += ;
}
if ((v & 0xff) == )
{
v >>= ;
c += ;
}
if ((v & 0xf) == )
{
v >>= ;
c += ;
}
if ((v & 0x3) == )
{
v >>= ;
c += ;
}
c -= v & 0x1;
} // 方法四
float f = (float)(v & -v);
r = (*(unsigned int *)&f >> ) - 0x7f; // 方法五
static const int Mod37BitPosition[] =
{ , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,, , , , };
r = Mod37BitPosition[(-v & v) % ]; // 方法六
static const int MultiplyDeBruijnBitPosition[] =
{ , , , , , , , , , , , , , , , ,, , , , , , , , , , , , , , , };
r = MultiplyDeBruijnBitPosition[((uint32_t)((v & -v) * 0x077CB531U)) >> ];

▶ 计算不小于 unsigned int v 的最小的 2 的整数次幂,结果放入 unsigned int r 。

 // 方法一
if (v > )
{
float f = (float)v;
unsigned int const t = 1U << ((*(unsigned int *)&f >> ) - 0x7f);
r = t << (t < v);
}
else
r = ; // 方法二,已知 1 < v < (1 << 25)
float f = (float)(v - );
r = 1U << ((*(unsigned int*)(&f) >> ) - ); // 方法三
v--;
v |= v >> ;
v |= v >> ;
v |= v >> ;
v |= v >> ;
v |= v >> ;
v++;

▶ 将 unsigned short x 和 unsigned short y 的二进制表示交替排列组成 unsigned int z,使得 z 的偶数位是 x,奇数位是 y 。

 // 方法零
#pragma unroll
for (int i = ; i < sizeof(x) * CHAR_BIT; i++)
z |= (x & 1U << i) << i | (y & 1U << i) << (i + ); // 方法一
static const unsigned short MortonTable256[] =
{
0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015,
0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055,
0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115,
0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155,
0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415,
0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455,
0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515,
0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555,
0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015,
0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055,
0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115,
0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155,
0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415,
0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455,
0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515,
0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555,
0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015,
0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055,
0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115,
0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155,
0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415,
0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455,
0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515,
0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555,
0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015,
0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055,
0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115,
0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155,
0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415,
0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455,
0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515,
0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555
}; z = MortonTable256[y >> ] << | MortonTable256[x >> ] << | MortonTable256[y & 0xFF] << | MortonTable256[x & 0xFF]; // 方法二
z = ((x * 0x0101010101010101ULL & 0x8040201008040201ULL) * 0x0102040810204081ULL >> ) & 0x5555|
((y * 0x0101010101010101ULL & 0x8040201008040201ULL) * 0x0102040810204081ULL >> ) & 0xAAAA; // 方法三
static const unsigned int B[] = { 0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF };
static const unsigned int S[] = { , , , };
x = (x | (x << S[])) & B[];
x = (x | (x << S[])) & B[];
x = (x | (x << S[])) & B[];
x = (x | (x << S[])) & B[];
y = (y | (y << S[])) & B[];
y = (y | (y << S[])) & B[];
y = (y | (y << S[])) & B[];
y = (y | (y << S[])) & B[];
z = x | (y << );

▶ 判断 unsigned int v 的二进制表示中是否有某一个字节为 0x00,结果放入 bool f 。

 // 方法零
unsigned char * p = (unsigned char *)&v;
f = *p && *(p + ) && *(p + ) && *(p + ); // 方法一
f = ((v & 0xff) && (v & 0xff00) && (v & 0xff0000) && (v & 0xff000000)); // 方法二,操作数更少
f = ~((((v & 0x7F7F7F7F) + 0x7F7F7F7F) | v) | 0x7F7F7F7F); // 方法三,最高字节为 0x80 是也会输出 true
f = ((v + 0x7efefeff) ^ ~v) & 0x81010100;
if (f)
f = ~((((v & 0x7F7F7F7F) + 0x7F7F7F7F) | v) | 0x7F7F7F7F); // 方法四
f = (((v)-0x01010101UL) & ~(v) & 0x80808080UL);

▶ 判断 unsigned int v 的二进制表示中是否有某一个字节等于 unsigned char n,结果放入 bool f 。

 f = (haszero((x) ^ (~0UL /  * (n))));

▶ 判断 unsigned int v 的二进制表示中是否有某一个字节小于 unsigned char n,结果放入 bool f 。

 // 方法一,要求 x ≥ 0,0 ≤ n ≤ 128
f = (((x)-~0UL / * (n))&~(x)&~0UL / * ); // 顺便计算到底有几个
int count = (((~0UL / * ( + (n)) - ((x)&~0UL / * ))&~(x)&~0UL / * ) / % );

▶ 判断 unsigned int v 的二进制表示中是否有某一个字节大于 unsigned char n,结果放入 bool f 。

 // 方法一,要求 x ≥ 0,0 ≤ n ≤ 127
f = (((x)+~0UL / * ( - (n)) | (x))&~0UL / * ); // 顺便计算到底有几个
int count = (((((x)&~0UL / * ) + ~0UL / * ( - (n)) | (x))&~0UL / * ) / % );

▶ 判断 unsigned int v 的二进制表示中是否有某一个字节大于 unsigned char n,结果放入 bool f 。

 // 方法一,要求 x ≥ 0,0 ≤ m ≤ n ≤ 128,m < 128
f = ((((x)-~0UL / * (n))&~(x)&((x)&~0UL / * ) + ~0UL / * ( - (m)))&~0UL / * ); // 方法二,要求 x ≥ 0,0 ≤ m ≤ n ≤ 128,m < 128
f = ((~0UL / * ( + (n)) - ((x)&~0UL / * )&~(x)&((x)&~0UL / * ) + ~0UL / * ( - (m)))&~0UL / * ); // 顺便计算到底有几个
int count = (hasbetween(x, m, n) / % );

▶ 给定 unsigned int v,计算二进制表示中 v 的词典序后继,且非零位个数与 v 相等的 unsigned int w 。

 // 方法一,使用了 GNU C compiler 的内联函数 __builtin_ctz() 计算尾 0 个数,
// MS compiler 中用 is _BitScanForward(),或使用前面求尾 0 个数的方法
unsigned int t = v | (v - );
w = (t + ) | (((~t & -~t) - ) >> (__builtin_ctz(v) + )); // 方法二,较慢,但不需要求尾 0 个数
unsigned int t = (v | (v - )) + ;
w = t | ((((t & -t) / (v & -v)) >> ) - );

位运算骚操作 Part 2的更多相关文章

  1. 位运算骚操作 Part 1

    ▶ 原文标题<Bit Twiddling Hacks>,地址:https://graphics.stanford.edu/~seander/bithacks.html ▶ 额外参考资料:h ...

  2. 位运算骚操作 Part 3

    ▶ 异或运算 "^" 具有的部分性质: ● 交换律,结合律 ● a ^ b == (!a & b) | (a & !b),a ^ 1 == !a,a ^ 0 == ...

  3. java位运算(操作)的使用

    位操作是程序设计中对位模式按位或二进制数的一元和二元操作. 在许多古老的微处理器上, 位运算比加减运算略快, 通常位运算比乘除法运算要快很多. 在现代架构中, 情况并非如此:位运算的运算速度通常与加法 ...

  4. C 碎片九 预处理&位运算&文件操作

    一.预处理 预处理语句:#开头的语句,在预处理阶段处理预处理语句.包括宏定义.文件包含处理.条件编译 1, 宏定义 1. 不带参数宏定义:#define 标识符  字符串 #define PI 3.1 ...

  5. LeetCode | 289. 生命游戏(原地算法/位运算)

    记录dalao的位运算骚操作 根据百度百科 ,生命游戏,简称为生命,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机. 给定一个包含 m × n 个格子的面板,每一个格子都可以看成是一个细 ...

  6. 位运算之——按位与(&)操作——(快速取模算法)

    学习redis 字典结构,hash找槽位 求槽位的索引值时,用到了 hash值 & sizemask操作, 其后的scan操作涉及扫描顺序逻辑,对同模的槽位 按一定规则扫描! 其中涉及位运算 ...

  7. 【Java基础】14、位运算之——按位与(&)操作——(快速取模算法)

    学习redis 字典结构,hash找槽位 求槽位的索引值时,用到了 hash值 & sizemask操作, 其后的scan操作涉及扫描顺序逻辑,对同模的槽位 按一定规则扫描! 其中涉及位运算 ...

  8. 全国计算机等级考试二级教程-C语言程序设计_第15章_位运算

    位运算,不适用于实数,仅仅适用于整数.字符. C语言的位运算只能操作整数.字符,实数是指数方式表示的,不适用于位运算. #define _CRT_SECURE_NO_WARNINGS #include ...

  9. LeetCode解题中位运算的运用

    位运算是我最近才开始重视的东西,因为在LeetCode上面刷题的时候发现很多题目使用位运算会快很多.位运算的使用包含着许多技巧(详细可以参考http://blog.csdn.net/zmazon/ar ...

随机推荐

  1. HDU 3342:Legal or Not(拓扑排序)

    Legal or Not Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tot ...

  2. POJ 3253 Fence Repair STL 优先队列

    这题做完后觉得很水,主要的想法就是逆过程思考,原题是截断,可以想成是拼装,一共有n根木棍,最后要拼成一根完整的,每两根小的拼成一根大的,拼成后的木棍长度就是费用,要求费用最少.显然的是一共会拼接n-1 ...

  3. C4D 计算体积和表面积插件

    前段时间,由于有个模型要做3D打印,所以需要知道模型的体积以及表面积,以便计算价格. 我用的是C4D,恕我愚昧,在C4D上没找到自带的. 在网上找了好久,才找到一个由法国开发名为aire_volume ...

  4. (1)集合 ---遍历map集合

    Map接口     实现Map接口的类用来存储键(key)-值(value) 对.Map 接口的实现类有HashMap和TreeMap等.Map类中存储的键-值对通过键来标识,所以键值不能重复. Ha ...

  5. HDU6387 AraBellaC

    题意 AraBellaC Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tota ...

  6. leetcode:Count and Say【Python版】

    一次AC 字符串就是:count+char class Solution: # @return a string def countAndSay(self, n): str = " for ...

  7. ballerina 学习二十八 快速grpc 服务开发

    ballerina 的grpc 开发模型,对于开发者来说简单了好多,不是schema first 的方式,而是我们 只要编写简单的ballerina service 就可以了,proto 文件是自动帮 ...

  8. scylladb docker 运行试用

      scylladb 是兼容cassandra 的数据存储系统,从官方的性能报告,比原生的apache cassandra 有好多 的提高 使用docker 运行,具体的也可以参考官方文档,后边会提供 ...

  9. 【转】朱兆祺教你如何攻破C语言学习、笔试与机试的难点(连载)

    原文网址:http://bbs.elecfans.com/jishu_354666_1_1.html 再过1个月又是一年应届毕业生应聘的高峰期了,为了方便应届毕业生应聘,笔者将大学四年C语言知识及去年 ...

  10. BASIC-16_蓝桥杯_分解质因数

    代码示例: #include <stdio.h> int i = 0 ;int Primes(int a){ for (i = 2 ; i <= a/2 ; i ++) { if ( ...