我一直在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等间隔返回正确的移位量?我最近一直在研究很多,但我似乎无法理解为什么会这样做。
答案 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
}