按位移位以及此解决方案为何有效
Bitwise bit shifting and why this solution works
我一直在 codefights.com 上打代码,我在下面遇到了这个问题。我已经自己解决了这个问题,但是当我研究其他人的解决方案时,我发现一个比我的短得多的解决方案,但我似乎无法理解他们为什么这样做。
问题是:
You are given an array of up to four non-negative integers, each less than 256.
Your task is to pack these integers into one number M in the following way:
The first element of the array occupies the first 8 bits of M;
The second element occupies next 8 bits, and so on.
Return the obtained integer M.
Note: the phrase "first bits of M" refers to the least significant bits of M - the right-most bits of an integer. For further clarification see the following example.
Example
For a = [24, 85, 0], the output should be
arrayPacking(a) = 21784.
An array [24, 85, 0] looks like [00011000, 01010101, 00000000] in binary.
After packing these into one number we get 00000000 01010101 00011000 (spaces are placed for convenience), which equals to 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 等间隔返回正确的偏移量?我最近一直在按位研究很多,但我似乎仍然无法理解为什么会这样。
按 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
}
或者您的问题是为什么这种包装有效?
首先,用Go编写解决方案。我们将 little-endian、base-256 数字转换为 base-2(二进制)数字。左移8位乘以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)
}
游乐场:https://play.golang.org/p/oo_n7CiAHwG
输出:
21784
现在你应该能猜出他们丑陋的答案了:
func arrayPacking(a []int) (sum int) {
for i := range a {
sum += a[len(a) - i - 1] << uint((len(a) - i - 1) * 8)
}
return
}
我一直在 codefights.com 上打代码,我在下面遇到了这个问题。我已经自己解决了这个问题,但是当我研究其他人的解决方案时,我发现一个比我的短得多的解决方案,但我似乎无法理解他们为什么这样做。
问题是:
You are given an array of up to four non-negative integers, each less than 256. Your task is to pack these integers into one number M in the following way:
The first element of the array occupies the first 8 bits of M; The second element occupies next 8 bits, and so on. Return the obtained integer M.
Note: the phrase "first bits of M" refers to the least significant bits of M - the right-most bits of an integer. For further clarification see the following example.
Example
For a = [24, 85, 0], the output should be arrayPacking(a) = 21784.
An array [24, 85, 0] looks like [00011000, 01010101, 00000000] in binary. After packing these into one number we get 00000000 01010101 00011000 (spaces are placed for convenience), which equals to 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 等间隔返回正确的偏移量?我最近一直在按位研究很多,但我似乎仍然无法理解为什么会这样。
按 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
}
或者您的问题是为什么这种包装有效?
首先,用Go编写解决方案。我们将 little-endian、base-256 数字转换为 base-2(二进制)数字。左移8位乘以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)
}
游乐场:https://play.golang.org/p/oo_n7CiAHwG
输出:
21784
现在你应该能猜出他们丑陋的答案了:
func arrayPacking(a []int) (sum int) {
for i := range a {
sum += a[len(a) - i - 1] << uint((len(a) - i - 1) * 8)
}
return
}