按位移位以及此解决方案的工作原理

时间:2018-01-23 17:05:19

标签: arrays go bit-manipulation bit shift

我一直在codefights.com上进行代码争夺,我在下面遇到了这个问题。我自己已经找到了问题,但是当我研究其他人的解决方案时,我发现了一个比我的短得多的解决方案,但我似乎无法理解为什么他们会做他们所做的事情。

问题是:

  

您将获得一个最多包含四个非负整数的数组,每个整数小于256。   您的任务是按以下方式将这些整数打包成一个数字M:

     

数组的第一个元素占据M的前8位;   第二个元素占用接下来的8位,依此类推。   返回获得的整数M。

     

注意:短语" M"的第一位;指的是M的最低有效位 - 整数的最右位。有关进一步说明,请参阅以下示例。

     

实施例

     

对于a = [24,85,0],输出应为   arrayPacking(a)= 21784。

     

数组[24,85,0]看起来像二进制的[00011000,01010101,00000000]。   将这些包装成一个数字后,我们得到00000000 01010101 00011000(方便放置空格),相当于21784。

他们的回答是:

func arrayPacking(a []int) (sum int) {
    for i := range a {
        sum += a[len(a) - i - 1] << uint((len(a) - i - 1) * 8)
    }
    return
}

这段代码如何仅使用0,8,16等间隔返回正确的移位量?我最近一直在研究很多,但我似乎无法理解为什么会这样做。

2 个答案:

答案 0 :(得分:1)

8的倍数的位移与256的倍数的倍增相同,例如, x << 0*8 == x * 256⁰x << 1*8 == x * 256¹x << 2*8 == x * 256²等,因此代码可以使用math.Pow重写:

func arrayPacking(a []int) (sum int) {
  for i := range a {
    sum += a[len(a) - i - 1] * int(math.Pow(256, (len(a) - i - 1)))
  }
  return
}

或者你的问题是为什么这种包装有效?

答案 1 :(得分:1)

First, write the solution in Go. We convert little-endian, base-256 digits to a base-2 (binary) number. Shifting left by 8 bits multiplies by 256.

package main

import (
    "fmt"
)

func pack(digits []int) (number int) {
    // digits are little-endian, base-256 (1 << 8 = 256)
    for i, digit := range digits {
        number += digit << uint(i*8)
    }
    return number
}

func main() {
    a := []int{24, 85, 0}
    m := pack(a)
    fmt.Println(m)
}

Playground: https://play.golang.org/p/oo_n7CiAHwG

Output:

21784

Now you should be able to figure out their ugly looking answer:

func arrayPacking(a []int) (sum int) {
    for i := range a {
        sum += a[len(a) - i - 1] << uint((len(a) - i - 1) * 8)
    }
    return
}