File tree 6 files changed +229
-0
lines changed
6 files changed +229
-0
lines changed Original file line number Diff line number Diff line change
1
+ .idea
Original file line number Diff line number Diff line change
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
+
Original file line number Diff line number Diff line change
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
+ }
Original file line number Diff line number Diff line change
1
+ module github.com/cryptography-research-lab/middle-square-method
2
+
3
+ go 1.18
Original file line number Diff line number Diff line change
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
+ }
Original file line number Diff line number Diff line change
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
+ }
You can’t perform that action at this time.
0 commit comments