▶ 计算 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. 51Nod:1265 四点共面

    计算几何 修改隐藏话题 1265 四点共面  基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 给出三维空间上的四个点(点与点的位置均不相同),判断这4个点 ...

  2. int? 竟然真的可以是 null!.NET/C# 确定可空值类型 Nullable 实例的真实类型

    使用 Nullable<T> 我们可以为原本不可能为 null 的值类型像引用类型那样提供一个 null 值.不过注意:Nullable<T> 本身也是个 struct,是个值 ...

  3. pipelinedb Continuous transforms 操作

    Continuous transforms 可以进行数据的转换,数据是不进行存储,主要是可以加入到其他的stream pipeline 中,或者写到其他外部 存储中,和存储过程结合使用,当前默认内置一 ...

  4. 彻底删除vscode及安装的插件和个人配置信息

    1.卸载vscode应用软件(在控制面板里面找不到改软件,所以只能进入应用所在文件夹进行卸载) ## 此步骤虽然删掉了应用软件,但是此时重新安装会发现之前下载的插件和个人配置信息都还会重新加载出来,所 ...

  5. 环境搭建之JAVA项目部署步骤

    一.配置java环境 1.linux下安装jdk,在此处安装1.7_x64的jdk,解压缩  tar -zxvf xxxxxxx 2.将jdk移动到/usr下 mv java /user/ 3.配置环 ...

  6. k最邻近算法——加权kNN

    加权kNN 上篇文章中提到为每个点的距离增加一个权重,使得距离近的点可以得到更大的权重,在此描述如何加权. 反函数 该方法最简单的形式是返回距离的倒数,比如距离d,权重1/d.有时候,完全一样或非常接 ...

  7. Dynamics CRM 2011 快速查找 出现异常 QuickFindQueryRecordLimit exceeded. Cannot perform this operation 的解决方法

    一.CRM 2011 快速查找,输入编号的签名几个字母发现查询很慢. 图 1 当然在图1 上右边的出入框输入编号的部分的时候,有时候会发现数据在加载中..,非常慢,通过Crm Trace Log Vi ...

  8. bootstrap+font-awesome表单

    bootstrap+font-awesome表单 <form action="" class="form-horizontal col-sm-offset-4&qu ...

  9. 多线程实现ping扫描

    代码: # coding=utf-8 import subprocess from Queue import Queue import threading class Pinger(object): ...

  10. make -j [N] --jobs [=N] 增加效率

    阿里云的服务器,以前是最低配1核心cpu,make的时候非常慢.升级配置以后,发现make的效率丝毫没有增加.top命令查看发现cpu的利用率非常低,于是执行命令: make --help 在显示的结 ...