ch2/ch2-06 #195
Replies: 10 comments 3 replies
-
练习 2.3 package main
import (
"fmt"
"time"
)
// 0-255 每个数值包含的 1 的位数(八位数值)
var pc = func() (pc [256]byte) {
for i := range pc {
pc[i] = pc[i>>1] + byte(i&1)
}
return
}()
func PopCount(x uint64) int {
return int(pc[byte(x>>(0*8))] + // 最低 8 位
pc[byte(x>>(1*8))] +
pc[byte(x>>(2*8))] +
pc[byte(x>>(3*8))] +
pc[byte(x>>(4*8))] +
pc[byte(x>>(5*8))] +
pc[byte(x>>(6*8))] +
pc[byte(x>>(7*8))]) // 最高 8 位
}
func main() {
arr := make([]int, 10000000)
for i := range arr {
arr[i] = i + 1
}
start := time.Now()
for _, v := range arr {
PopCount(uint64(v))
}
fmt.Printf("pc cost: %d ms\n", time.Since(start).Milliseconds()) // 1ms
start = time.Now()
for _, v := range arr {
PopCount2(uint64(v))
}
fmt.Printf("loop cost: %d ms\n", time.Since(start).Milliseconds()) // 48ms
}
func PopCount2(x uint64) int {
count := 0
for x != 0 {
if x&1 == 1 {
count++
}
x >>= 1
}
return count
} |
Beta Was this translation helpful? Give feedback.
-
package main
import (
"fmt"
)
func main() {
fmt.Println(PopCount(9999))
fmt.Println(PopCountEach1(9999))
fmt.Println(PopCountEach8(9999))
fmt.Println(PopCount0(9999))
}
var pc [256]byte
func init() {
for i := range pc {
pc[i] = pc[i/2] + byte(i&1)
}
}
// PopCount returns the population count (number of set bits) of x.
func PopCount(x uint64) int {
return int(pc[byte(x>>(0*8))] +
pc[byte(x>>(1*8))] +
pc[byte(x>>(2*8))] +
pc[byte(x>>(3*8))] +
pc[byte(x>>(4*8))] +
pc[byte(x>>(5*8))] +
pc[byte(x>>(6*8))] +
pc[byte(x>>(7*8))])
}
func PopCountEach1(x uint64) int {
var res int
for x > 0 {
if x&1 > 0 {
res++
}
x = x>>1
}
return res
}
func PopCountEach8(x uint64) int {
var res int
for step := 7; step >= 0; step-- {
res += int(pc[byte(x>>(8 * step))])
}
return res
}
func PopCount0(x uint64) int {
var res int
for x > 0 {
x &= x-1
res++
}
return res
} |
Beta Was this translation helpful? Give feedback.
-
onebitcount.go var onebitMap [256]byte func init(){ func OnebitFoundamental(x uint64) int { func Onebit23(x uint64) int { func OnebitShift24(x uint64) int { // x & (x - 1) 能够将 x 的最后一个非 零 bit 位清零 /*
练习 2.5:
表达式 x & (x - 1) 用于将 x 的最低一个非零的 bit 位清零。
使用这个算法重写 PopCount 函数,然后比较性能
结果: 统一来说
testFoundamental: 1.378473526 s
testLoop23: 18.059520553 s
testShift24: 24.736205763 s
testClear25: 18.931325779 s
总结来说,查表最快,其次将查表写成循环的速度约等于 x & (x - 1), 最慢的是每次移动最后一位 x >>= 1 的做法
*/
package main
import (
"fmt"
"onebitcount"
"time"
)
func testFoundamental(){
start := time.Now()
var i uint64
for i = 0; i < 1024 * 1024 * 1024; i++ {
onebitcount.OnebitFoundamental(i)
}
fmt.Printf("testFoundamental: %vs\n", time.Since(start).Seconds())
}
func test23(){
start := time.Now()
var i uint64
for i = 0; i < 1024 * 1024 * 1024; i++ {
onebitcount.Onebit23(i)
}
fmt.Printf("testLoop23: %vs\n", time.Since(start).Seconds())
}
func test24(){
start := time.Now()
var i uint64
for i = 0; i < 1024 * 1024 * 1024; i++ {
onebitcount.OnebitShift24(i)
}
fmt.Printf("testShift24: %vs\n", time.Since(start).Seconds())
}
func test25(){
start := time.Now()
var i uint64
for i = 0; i < 1024 * 1024 * 1024; i++ {
onebitcount.OnebitClear25(i)
}
fmt.Printf("testClear25: %vs\n", time.Since(start).Seconds())
}
func main(){
testFoundamental()
test23()
test24()
test25()
} 文件目录结构 onebitcount / onebitcount.go go mod init onebitcount 在 test 文件夹里输入 go build test.go |
Beta Was this translation helpful? Give feedback.
-
2.2 import ( type Meter float64 func (m Meter) String() string { return fmt.Sprintf("%gM", m) } // MToKm converts a Meter temperature to Kilometer. func KmToM(km Kilometer) Meter { return Meter(km * 1000) } func main() { |
Beta Was this translation helpful? Give feedback.
-
package main import ( // pc[i] is the population count of i. func init() { // PopCount1 returns the population count (number of set bits) of x. // PopCount2 returns the population count (number of set bits) of x. func main() {
} |
Beta Was this translation helpful? Give feedback.
-
这段翻译不太准确。
应该翻译成: |
Beta Was this translation helpful? Give feedback.
-
func PopCountLoop(x uint64) int { func PopCountMove(x uint64) int { func PopCountClean(x uint64) int { |
Beta Was this translation helpful? Give feedback.
-
package main import ( func count(c1 [32]byte, c2 [32]byte) int {
} // 逐位进行比较 func main() { |
Beta Was this translation helpful? Give feedback.
-
package main
import "fmt"
import "time"
var pc [256]byte = func() (p [256]byte) {
for i := range p {
p[i] = p[i>>1] + byte(i&1)
}
return
}()
func PopCount1(x uint64) int {
return int(pc[byte(x>>(0*8))] +
pc[byte(x>>(1*8))] +
pc[byte(x>>(2*8))] +
pc[byte(x>>(3*8))] +
pc[byte(x>>(4*8))] +
pc[byte(x>>(5*8))] +
pc[byte(x>>(6*8))] +
pc[byte(x>>(7*8))])
}
func PopCount2(x uint64) (cnt int) {
for i := 0; i < 8; i++ {
cnt += int(pc[byte(x>>(8*i))])
}
return
}
func PopCount3(x uint64) (cnt int) {
for x > 0 {
if x&1 > 0 {
cnt++
}
x >>= 1
}
return
}
func PopCount4(x uint64) (cnt int) {
for x > 0 {
cnt++
x &= x-1
}
return
}
func test1() {
start := time.Now()
var i uint64
for i = 0; i < 1024 * 1024 * 1024; i++ {
PopCount1(i)
}
fmt.Printf("test1: %vs\n", time.Since(start).Seconds())
}
func test2() {
start := time.Now()
var i uint64
for i = 0; i < 1024 * 1024 * 1024; i++ {
PopCount2(i)
}
fmt.Printf("test2: %vs\n", time.Since(start).Seconds())
}
func test3() {
start := time.Now()
var i uint64
for i = 0; i < 1024 * 1024 * 1024; i++ {
PopCount3(i)
}
fmt.Printf("test3: %vs\n", time.Since(start).Seconds())
}
func test4(){
start := time.Now()
var i uint64
for i = 0; i < 1024 * 1024 * 1024; i++ {
PopCount4(i)
}
fmt.Printf("test4: %vs\n", time.Since(start).Seconds())
}
func main(){
test1()
test2()
test3()
test4()
} |
Beta Was this translation helpful? Give feedback.
-
ch2/ch2-06
中文版
https://gopl-zh.github.io/ch2/ch2-06.html
Beta Was this translation helpful? Give feedback.
All reactions