【问题标题】:division and multiplication by power of 2除法和乘以 2 的幂
【发布时间】:2014-11-05 09:53:54
【问题描述】:

我在一篇论文中读到,一个数字除以 2 的幂是一个简单的过程。 我在互联网上搜索了很多解释,但没有得到它。 谁能用简单的话解释一下这实际上是什么意思。

【问题讨论】:

  • 人类的除法乘以10是一样的。你怎么能把任何数字乘以 10?只需添加一个零。
  • 小心:一旦您尝试跟踪乘法时的溢出或除法时的余数,它可能不像您希望的那样微不足道。

标签: binary bit-manipulation computer-science division multiplication


【解决方案1】:

从位操作的角度来看,这是微不足道的。乘以 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) &gt;&gt; 1 == -3。实现有符号除以 2 仍然可以通过移位 + 额外操作来添加符号位以获得截断行为。 (查看 C 编译器输出。)

【讨论】:

    【解决方案2】:

    由于所有数字都以二进制形式存储,因此乘法/除法是一种简单的位移运算。

    例如(乘法):

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

    这同样适用于除法(右位移操作),但如果需要余数,则需要考虑奇数除法的进位。

    【讨论】:

      【解决方案3】:

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

      这样做的原因是,除以某些数字系统(二进制、八进制、十六进制,等等)的基数时,总是可以通过简单的数字右移来完成。

      例如,在十进制除以十的情况下,您有:

      230.0 / 10.0 = 23.00 
      

      (将小数点左移一位,即数字右移)

      十六进制数也一样:

      0xA2FF / 0x10 = 0xA2F 
      

      (数字右移一位)

      对于二进制数也是如此:

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

      如果要除以 2 的幂,则需要执行的右移次数对应于指数。例如,除以 4 表示除以 2*2,等于两次右移操作:

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

      【讨论】:

      • 二进制浮点格式(例如IEEE754 binary64 aka double)只需在指数字段中加减就可以很便宜地乘以或除以2的幂! (不过,您必须检查是否有溢出)。硬件并不总是将此作为单独的操作提供,因此您通常只需将0.5 与常规指令相乘即可。 AVX512F 有,带有vscalefsd (scale scalar double by 2^floor(x)),以及相关的浮点和 SIMD 版本
      • 我猜这就是你所说的less琐碎的意思,而不是not琐碎的,但是对于硬件来说实现起来相当琐碎。
      【解决方案4】:

      基本上是一个数的2次方的乘除,如果用二进制表示,只需要把所有的二进制位左移或右移即可:

      00100 即 4,如果你想乘以 2*2*2,你只需将剩下的所有数字翻译 3 次:

      100000 正好是 32 (4 * 8 = 32)

      反之亦然

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-03-08
        • 1970-01-01
        • 1970-01-01
        • 2014-03-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-19
        • 1970-01-01
        相关资源
        最近更新 更多