您当前的位置: 首页 > 热点 > > 内容页

【世界热闻】移位运算

来源:博客园 2023-04-30 22:26:19


【资料图】

概述

这里以C语言为例描述移位运算的行为。 对于一个位表示为 \(x_{w-1}\), \(x_{w-2}\) ,..., \(x_{0}\) 的操作数 x, C 表达式 \(x << k\) 会生成一个値,其位表示为 \([\) \(x_{w-k-1}\), \(x_{w-k-2}\) ,..., \(x_{0}\),0,... , 0 \(]\) 。也就是说,x 向左移动 k 位,丢弃最高的 k 位,并在右端补 k 个 0。移位量应该是一个 0 ~ w - 1 之间的值。移位运算是从左至右可结合的,所以 \(x << j << k\) 等价于 \((x << j) << k\)。

有一个相应的右移运算 \(x>>k\),但是它的行为有点微妙。一般而言,机器文持两种形式的右移: 逻辑右移和算术右移。逻辑右移在左端补 k 个零,得到的结果是 \([\) 0 , ... , 0 , \(x_{w-1}\),\(x_{w-2}\) , ... ,\(x_k\) \(]\)。算术右移是在左端补 k 个最高有效位的值,得到的结果是 \([\) \(x_{w-1}\), ..., \(x_{w-1}\), \(x_{w-1}\),\(x_{w-2}\), ..., \(x_k\) \(]\)。这种做法看上去可能有点奇特,但是我们会发现它对有符号整数数据的运算非常有用。

让我们来看一个例子,下面的表给出了对一个8位参数 × 的两个不同的值做不同的移位操作得到的结果:

操作
参数x[011000111] [100101011]
x << 4[00110000] [01010000]
× > 4 (逻辑右移)[00000110] [000010011]
x>>4 (算术右移)[00000110] [11111001]

可以看到除了一个条目之外,其他的都包含填充0。唯一的例外是算术右移 [10010101] 的情况。因为操作数的最高位是1,填充的値就是1。C语言标准并没有明确定义对于有符号数应该使用哪种类型的右移——算术右移或者逻辑右移都可以。不幸地,这就意味着任何假设一种或者另一种右移形式的代码都可能会遇到可移植性问题。然而,实际上,几乎所有的编译器/机器组合都对有符号数使用算术右移,且许多程序员也都假设机器会使用这种右移。另一方面,对于无符号数,右移必须是逻辑的。

与C相比,Java 对于如何进行右移有明确的定义。表达是 \(x>>k\) 会将 × 算术右移 k 个位置,而 \(x >>> k\) 会对 × 做逻辑右移。

逻辑右移

在 C/C++ 中如果要对有符号数进行逻辑右移,那么不能简单的使用 x >> k,因为对于负数会用符号位填充左端的 k 位。因此要进行逻辑右移,我们使用一个数来记录前 k 位,使其前 k 位都是0,其余都是1,然后与 x >> k的结果做与运算。

// 由于无符号数右移一定是逻辑右移,因此先转换为无符号数,得到前k位都是0,然后再转换为有符号数int logic_r_shift(int x, int k) {    return (int)((unsigned int)x >> k);}

网上还流传有另一种写法:

// mask 得到一个前 k 位都是0的数,但是由于 >> 的运算符对于有符号数在C中并没有明确定义(即使大部分编译器都使用了算数右移)// 所以即使以下代码可以正常运行,但并不保证没有可移植问题int logical_right_shift(int x, int k){    int size = sizeof(int) * 8; // usually sizeof(int) is 4 bytes (32 bits)    int mask = ~(((0x1 << size) >> k) << 1)    return (x >> k) & mask;}

C++中可以通过模板函数和 union 的结合实现一个通用的逻辑右移运算。

template   union Converter {      static_assert(sizeof(T) == sizeof(P), "size not match");      T first;      P second;  };static inline uint32_t Int32ToUInt32(int32_t v) {      Converter converter;      converter.first = v;      return converter.second;  }    static inline int32_t UInt32ToInt32(uint32_t v) {      Converter converter;      converter.second = v;      return converter.first;  }static inline int32_t logicalRightShift32(int32_t value, uint32_t spaces) {      return UInt32ToInt32((Int32ToUInt32(value) >> spaces));  }
上一篇 下一篇
x
推荐阅读 更多
【世界热闻】移位运算

概述这里以C语言为例描述移位运算的行为。对于一个位表示为$x_{w-1}$,$x_{w-2}$, ,$x_{0}$的操作数x,C表

2023-04-30
“五一”假期第二天全国道路交通总体平稳有序

4月30日电,“五一”假期第二天,全国大部分地区天气良好,各主要高速公路、国省道干线公路交通流量较昨日

2023-04-30
最美四“阅”天|以书为帆,御风远航

文、图|徐滔——写在《放歌长岛》诞生一周年高尔基说过:“书是人类进步的阶梯。”应该说,我们在日常的学

2023-04-30
裙子的拼音是几声_裙子的拼音

1、“裙子”的拼音是[qúnzi]。2、裙子,指一种围在腰部以下的服装,多为女子着装。3、它是人类最早的服装。

2023-04-30
每日聚焦:东莞市专业技术人才服务网登录系统_东莞市专业技术人才服务网

1、我也今年申请了,状态是“评审中”刚才我上了下,可以上的。2、你不能上查下别的原因吧。3、一般交了材

2023-04-30
每日快讯!石斛泡水喝一次放多少好_石斛泡水一次几个

解答:1、石斛一次可泡水2-3个;2、泡过水的石斛有独特的香味和甘爽的口感,长期饮用有益健康。3、石斛能清

2023-04-30
环球观点:景区回应“上厕所要花55元买门票”:园外无公厕

景区回应“上厕所要花55元买门票”:园外无公厕

2023-04-30
全球热消息:商人本质!马斯克计划出推特文章付费看制度

推特CEO马斯克今日更新推文表示,推特计划在下个月推出“单篇文章付费收看制度”。

2023-04-30
世界聚焦:2023年一季度全国网信行政执法与监督工作有序开展

App4月30日消息,2023年一季度,全国网信系统进一步加大网络执法力度,健全制度机制,增强工作队伍,规范网

2023-04-30
九龙福黄金价格今天多少一克(2023年04月30日) 快看

九龙福珠宝黄金价格今天多少一克(2023年04月30日)每日更新

2023-04-30