2

我在一篇论文中读到,一个数除以2的幂的乘除法是一个微不足道的过程。 我已经搜索了很多互联网的解释,但没有得到它。 任何人都可以用简单的话来解释这实际上是什么意思。除法和乘2的幂

+1

这与人类除以10并相乘相同。你怎么能把任何数字乘以10?只需添加一个零。 – usr2564301 2014-09-11 12:45:34

+1

小心:一旦你尝试跟踪溢出时的余数或余数时,它可能不会像你所希望的那样微不足道。 – 2014-09-11 13:06:32

回答

3

从位操作的角度来看这是微不足道的。乘以2相当于左移1位,划分是右移。同样它是相同的微不足道的乘法和除法以2

int a = 123;   // or in binary format: a = 0b01111011; 

assert (a * 2) == (a << 1); // 2 = 2^1, (a << 1) = 11110110 
assert (a/2) == (a >> 1); // 2 = 2^1, (a >> 1) = 00111101 

assert (a * 8) == (a << 3); // 8 = 2^3, (a << 3) = 1111011000 
assert (a/8) == (a >> 3); // 8 = 2^3, (a >> 3) = 0000001111 

任何功率还要注意的是a*2 = a+a,和加料有时比换档,这取决于硬件甚至更便宜。

对于带符号的分割,请注意在某些语言(如C)中,整数除法向零截断,而算术右移(移位2的补码符号位的副本)总是向-Infinity回绕。例如(-5)/2 == -2,但是(-5) >> 1 == -3。实现有符号除法2仍然可以通过shift +额外操作来添加符号位以获得截断行为。 (看看C编译器的输出。)

1

基本上乘法和除法一个数是2的幂,如果数字是以二进制表示的,你只需要翻译撇下所有的二进制数字或右:

00100是4,如果你想乘2 * 2 * 2,你只是把所有的号码留给3次:

100000是exaqctly 32(4×8 = 32)

到devide它周围的其他方法

2

由于所有数字都以二进制形式存储分区是一个简单的位移操作。

例如(乘法):

  • 5 = 101(二进制)
  • 5 * 2 = 10 = 1010(二进制) - 只是移位所有位1个位置向左
  • 5 * 4 = 20 = 10100(二进制) - 只将所有位向左移位2位置

同样适用于除法(右移位操作),但您需要考虑奇数除法的进位if你需要剩下的。

2

重要的是在这种情况下除以2(或2的幂)对于整数算术来说是微不足道的。当你谈论浮点除法时,它变得不那么琐碎。

其原因在于,通过数字的简单右移,总是可以通过一些数字系统(二进制,八进制,十六进制,您的名称)的基数除数来完成。

例如,在由10与除法十进制您有:

230.0/10.0 = 23.00 

(换档小数点一个位置向左侧,其转换为数字的右移位)

同样为十六进制数:

0xA2FF/0x10 = 0xA2F 

(数移位一个位置向右移)

与同为二进制数:

1101011/10 = 110101 (binary notation) 
107 /2 = 53  (decimal notation for the same equation) 

如果你想通过两种动力来划分,则需要执行对应于指数右移的数量。例如,除以4意味着除以2 * 2,等于两次右移操作:

1101011/100 = 11010 (binary notation, two shift operations) 
107 / 4 = 26 (decimal notation) 
+0

二进制浮点格式(如[IEEE754 binary64又名'double'](https://en.wikipedia.org/wiki/Double-precision_floating-point_format))可以便宜地乘以或除以2的幂,只需加上或减去来自指数字段! (虽然你必须检查溢出)。硬件并不总是将此作为单独的操作提供,因此通常您只需将常规指令乘以0.5即可。 AVX512F使用['vscalefsd'(通过'2^floor(x)')](https://hjlebbink.github.io/x86doc/html/VSCALEFSD.html)扩展标量,以及相关的float和SIMD版本 – 2017-12-04 01:44:39

+0

我想这就是你的意思,不是微不足道的,而是微不足道的,但是对于硬件来说,实现起来相当微不足道。 – 2017-12-04 01:45:47