Skip to content

Commit edb5d7f

Browse files
committed
init
1 parent ff8ee28 commit edb5d7f

File tree

6 files changed

+229
-0
lines changed

6 files changed

+229
-0
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.idea

Diff for: README.md

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# 平方取中法随机数生成器
2+
3+
# 一、平方取中法介绍
4+
5+
平方取中方法是1946年由John Von Neumann,S. Ulm和N. Metropolis 在Los Alamos实验室研究中子碰撞时提出的,这是一种用来生成随机数的算法,但是因为存在致命的缺陷,因此不适合用在生产环境中。
6+
7+
# 二、添加依赖
8+
9+
```bash
10+
go get -u github.com/cryptography-research-lab/middle-square-method
11+
```
12+
13+
注:此算法过于久远,仅作为技术研究,已经不适合用于生产环境,请谨慎使用。
14+
15+
# 三、API Example
16+
17+
```go
18+
package main
19+
20+
import (
21+
"fmt"
22+
middle_square_method "github.com/cryptography-research-lab/middle-square-method"
23+
)
24+
25+
func main() {
26+
27+
// 指定seed
28+
//generator := middle_square_method.NewMiddleSquareMethodRandomGenerator(123456788)
29+
// 不指定的话默认会把当前unix毫毛时间戳作为随机数序列的seed
30+
generator := middle_square_method.NewMiddleSquareMethodRandomGenerator()
31+
for i := 0; i < 10; i++ {
32+
fmt.Println(generator.Next())
33+
}
34+
// Output:
35+
// 8368732329101
36+
// 5929387542414
37+
// 5544795373933
38+
// 112994856646
39+
// 2690729443080
40+
// 9928319934722
41+
// 3156013888483
42+
// 1967977745017
43+
// 5593118728487
44+
// 833319471388
45+
46+
}
47+
```
48+
49+
# 四、平方取中法生成过程
50+
51+
1. 选择一个m位的数字作为随机数种子seed
52+
2. 把seed开方,得到结果r = seed * seed
53+
3. 如果r的位数不足2*m位,则左边补0到2 * m 位
54+
4. 然后取中间的m位作为生成的结果,同时作为下一次生成的seed
55+
5. 如此往复,便能生成随机数序列
56+
57+
# 五、 缺点
58+
59+
当多次生成的时候可能会退化为0
60+
61+
TODO 证明退化为0的过程
62+
63+
# 六、参考资料
64+
65+
- https://baike.sogou.com/v71147797.htm
66+
- https://www.cnblogs.com/hanyu1995/p/14658844.html
67+
68+
69+
70+
71+
72+
73+
74+
75+
76+
77+

Diff for: example/main.go

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
middle_square_method "github.com/cryptography-research-lab/middle-square-method"
6+
)
7+
8+
func main() {
9+
10+
// 指定seed
11+
//generator := middle_square_method.NewMiddleSquareMethodRandomGenerator(123456788)
12+
// 不指定的话默认会把当前unix毫毛时间戳作为随机数序列的seed
13+
generator := middle_square_method.NewMiddleSquareMethodRandomGenerator()
14+
for i := 0; i < 10; i++ {
15+
fmt.Println(generator.Next())
16+
}
17+
// Output:
18+
// 8368732329101
19+
// 5929387542414
20+
// 5544795373933
21+
// 112994856646
22+
// 2690729443080
23+
// 9928319934722
24+
// 3156013888483
25+
// 1967977745017
26+
// 5593118728487
27+
// 833319471388
28+
29+
}

Diff for: go.mod

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module github.com/cryptography-research-lab/middle-square-method
2+
3+
go 1.18

Diff for: middle_square_method.go

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package middle_square_method
2+
3+
import "time"
4+
5+
type MiddleSquareMethodRandomGenerator struct {
6+
length uint64
7+
seed uint64
8+
}
9+
10+
// NewMiddleSquareMethodRandomGenerator seed不指定的话默认为当前unix毫秒时间戳
11+
func NewMiddleSquareMethodRandomGenerator(seed ...uint64) *MiddleSquareMethodRandomGenerator {
12+
if len(seed) == 0 {
13+
seed = append(seed, uint64(time.Now().UnixMilli()))
14+
}
15+
return &MiddleSquareMethodRandomGenerator{
16+
length: computeLength(seed[0]),
17+
seed: seed[0],
18+
}
19+
}
20+
21+
func (x *MiddleSquareMethodRandomGenerator) SetLength(length uint64) {
22+
x.length = length
23+
}
24+
25+
func (x *MiddleSquareMethodRandomGenerator) SetSeed(seed uint64) {
26+
x.seed = seed
27+
}
28+
29+
func computeLength(seed uint64) uint64 {
30+
lengthCount := 0
31+
for seed > 0 {
32+
lengthCount++
33+
seed /= 10
34+
}
35+
return uint64(lengthCount)
36+
}
37+
38+
// Next 返回下一个随机数
39+
func (x *MiddleSquareMethodRandomGenerator) Next() uint64 {
40+
x.seed = x.takeMiddle(x.seed * x.seed)
41+
return x.seed
42+
}
43+
44+
func (x *MiddleSquareMethodRandomGenerator) takeMiddle(n uint64) uint64 {
45+
46+
// 先丢弃右边的length/2个字符
47+
needDropCount := x.length / 2
48+
for needDropCount > 0 {
49+
n /= 10
50+
needDropCount--
51+
}
52+
53+
// 然后取length个字符,作为获取到的中间的结果,如果长度不够的话则左边空着
54+
// 因为是数值类型,所以左边不能补0
55+
result := uint64(0)
56+
needTakeCount := x.length
57+
weight := 0
58+
for needTakeCount > 0 {
59+
result = (n%uint64(10))*x.pow(weight) + result
60+
n /= 10
61+
needTakeCount--
62+
weight++
63+
}
64+
return result
65+
}
66+
67+
// 计算10的n次幂
68+
func (x *MiddleSquareMethodRandomGenerator) pow(n int) uint64 {
69+
result := uint64(1)
70+
for n > 0 {
71+
result *= 10
72+
n--
73+
}
74+
return result
75+
}
76+
77+
// IsZero 判断当前是否已经退化为0了,这是平方取中法会有的缺陷,当退化为0的时候生成器便失效无法生成新的随机数
78+
func (x *MiddleSquareMethodRandomGenerator) IsZero() bool {
79+
return x.seed == 0
80+
}

Diff for: middle_square_method_test.go

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package middle_square_method
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
)
7+
8+
func Test(t *testing.T) {
9+
10+
//generator := NewMiddleSquareMethodRandomGenerator( 2041)
11+
generator := NewMiddleSquareMethodRandomGenerator(675248)
12+
for i := 0; i < 20; i++ {
13+
fmt.Println(generator.Next())
14+
}
15+
// Seed:
16+
// 2041
17+
//Output:
18+
// 1656
19+
// 7423
20+
// 1009
21+
// 180
22+
// 324
23+
// 1049
24+
// 1004
25+
// 80
26+
// 64
27+
// 40
28+
// 16
29+
// 2
30+
// 0
31+
// 0
32+
// 0
33+
// 0
34+
// 0
35+
// 0
36+
// 0
37+
// 0
38+
39+
}

0 commit comments

Comments
 (0)