Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 18 additions & 11 deletions labs31/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,29 @@

最直接的办法就是循环计算,因为2的20次幂就达到1M的大小了,这么大的内存块其实没有缓存的必要了,所以循环最多也就20次。

但是我很蛋疼了测试了sort包的Search函数,switch循环展开、if循环展开和人肉折半查找
但是我很蛋疼了测试了sort包的Search函数,switch循环展开、if循环展开、人肉折半查找、浮点数取指数

我电脑上测试结果如下:

```

go version 1.7.3

$ go test -bench="."
PASS`
Benchmark_Normal-8 100000000 22.8 ns/op
Benchmark_Search-8 100000000 21.5 ns/op
Benchmark_Search2-8 200000000 6.62 ns/op
Benchmark_Switch-8 200000000 7.54 ns/op
Benchmark_IF1-8 300000000 4.33 ns/op
Benchmark_IF2-8 500000000 2.71 ns/op
Benchmark_IF3-8 2000000000 1.09 ns/op
Benchmark_IF4-8 200000000 7.12 ns/op
Benchmark_IF5-8 2000000000 0.61 ns/op
PASS
Benchmark_Normal-4 50000000 25.6 ns/op
Benchmark_Search-4 100000000 21.7 ns/op
Benchmark_Switch-4 100000000 12.5 ns/op
Benchmark_IF1-4 200000000 9.14 ns/op
Benchmark_IF2-4 300000000 3.89 ns/op
Benchmark_IF3-4 1000000000 2.37 ns/op
ok github.com/idada/go-labs/labs31 11.822s
```
ok command-line-arguments 18.027s


呵呵,蛋好疼。

补充:最后一个IF3测试是由群里的v1zze同学提供的算法,果然牛逼。
补充:最后一个IF3测试是由群里的v1zze同学提供的算法,果然牛逼。
IF4 和 IF5 使用浮点数取指数计
65 changes: 63 additions & 2 deletions labs31/labs31_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package labs31

import (
"math"
"math/rand"
"sort"
"testing"
Expand All @@ -23,11 +24,14 @@ func Test_All(t *testing.T) {
d := IF2(n)
e := Search(n)
f := IF3(n)
g := IF4(n)
h := IF5(n)
i := SearchInt(n)
if f > 21 {
f = 21
}
if a != b || b != c || c != d || d != e || e != f {
t.Log(n, a, b, c, d, e, f)
if a != b || b != c || c != d || d != e || e != f || f != g || g != h || h != i {
t.Log(n, a, b, c, d, e, f, g, h, i)
t.Fail()
}
}
Expand All @@ -45,6 +49,12 @@ func Benchmark_Search(b *testing.B) {
}
}

func Benchmark_Search2(b *testing.B) {
for i := 0; i < b.N; i++ {
SearchInt(benchx)
}
}

func Benchmark_Switch(b *testing.B) {
for i := 0; i < b.N; i++ {
Switch(benchx)
Expand All @@ -69,6 +79,18 @@ func Benchmark_IF3(b *testing.B) {
}
}

func Benchmark_IF4(b *testing.B) {
for i := 0; i < b.N; i++ {
IF4(benchx)
}
}

func Benchmark_IF5(b *testing.B) {
for i := 0; i < b.N; i++ {
IF5(benchx)
}
}

func Normal(n int) uint {
var i = uint(0)
for ; n > (1<<i) && i <= 20; i++ {
Expand All @@ -85,6 +107,25 @@ func Search(n int) uint {
return uint(sort.SearchInts(classes, n))
}

// copy from search.go:59
// func Search(n int, f func(int) bool) int
func SearchInt(n int) uint {
// Define f(-1) == false and f(n) == true.
// Invariant: f(i-1) == false, f(j) == true.
i, j := 0, len(classes)
for i < j {
h := i + (j-i)/2 // avoid overflow when computing h
// i ≤ h < j
if classes[h] < n {
i = h + 1 // preserves f(i-1) == false
} else {
j = h // preserves f(j) == true
}
}
// i == j, f(i-1) == false, and f(j) (= f(i)) == true => answer is i.
return uint(i)
}

func Switch(n int) uint {
switch {
case n == 1:
Expand Down Expand Up @@ -299,3 +340,23 @@ func IF3(n int) uint {
}
return c
}

func IF4(n int) uint {
n--
ix := math.Ilogb(float64(n))
if ix > 20 {
ix = 20
}
ix++
return uint(ix)
}

func IF5(n int) uint {
n--
ix := (math.Float32bits(float32(n))>>23)&0xff - 127
if ix > 20 {
ix = 20
}
ix++
return uint(ix)
}