我想产生转到一个随机字符串,这里是到目前为止,我写的代码:
package main
import (
"bytes"
"fmt"
"math/rand"
"time"
)
func main() {
fmt.Println(randomString(10))
}
func randomString(l int) string {
var result bytes.Buffer
var temp string
for i := 0; i < l; {
if string(randInt(65, 90)) != temp {
temp = string(randInt(65, 90))
result.WriteString(temp)
i++
}
}
return result.String()
}
func randInt(min int, max int) int {
rand.Seed(time.Now().UTC().UnixNano())
return min + rand.Intn(max-min)
}
我的实现是很慢的。 采用播种time
一次又一次带来了一定的时间相同的随机数,所以循环迭代。 我怎样才能提高我的代码?
每次设置相同的种子时,你会得到相同的序列。 所以,当然,如果你设置种子的时间在一个快速循环,你可能会使用相同的种子多次调用它。
在你的情况,因为你打电话你randInt
功能,直到你有不同的值,你等待的时间(由纳米返回)改变。
对于所有的伪随机图书馆 ,你有你的初始化程序时,除非特别需要再现给定序列(通常仅用于调试和单元测试完成)设置种子仅一次,例如。
之后,你只需调用Intn
得到一个随机整数。
移动rand.Seed(time.Now().UTC().UnixNano())
从randInt功能线到主的开始,一切都将更快。
还需要注意的是,我认为可以简化您的字符串建筑:
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
rand.Seed(time.Now().UTC().UnixNano())
fmt.Println(randomString(10))
}
func randomString(l int) string {
bytes := make([]byte, l)
for i := 0; i < l; i++ {
bytes[i] = byte(randInt(65, 90))
}
return string(bytes)
}
func randInt(min int, max int) int {
return min + rand.Intn(max-min)
}
只是抛它出去后代:它有时可以是优选的,以产生使用初始字符集串的随机串。 如果该字符串应该是由人手动输入这是有用的; 不含0,O,1,和L可以帮助减少用户错误。
var alpha = "abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789"
// generates a random string of fixed size
func srand(size int) string {
buf := make([]byte, size)
for i := 0; i < size; i++ {
buf[i] = alpha[rand.Intn(len(alpha))]
}
return string(buf)
}
我通常设置内部的种子init()
块。 他们要在这里记载: http://golang.org/doc/effective_go.html#init
OK,为什么这么复杂!
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
rand.Seed( time.Now().UnixNano())
var bytes int
for i:= 0 ; i < 10 ; i++{
bytes = rand.Intn(6)+1
fmt.Println(bytes)
}
//fmt.Println(time.Now().UnixNano())
}
这是基于关闭dystroy的代码,但装我的需求。
这是死六(兰特整数1 =< i =< 6
func randomInt (min int , max int ) int {
var bytes int
bytes = min + rand.Intn(max)
return int(bytes)
}
上面的功能是完全一样的事情。
我希望这个信息是使用。
我不明白为什么人们有时间值播种。 这在我的经验,从来就不是一个好主意。 例如,当系统时钟在纳秒也许代表了系统的时钟精度不纳秒。
这个程序不应该转到操场上运行,但如果你在你的机器上运行它,你会得到你可以期望什么类型的精度的粗略估计。 我看到的100多万纳秒,所以1周毫秒为单位递增。 这一点用都没有熵的20位。 一直以来高位大多是不变的。
这对你很可能会有所不同,但你可以通过简单地使用基于避免时钟种子值的缺陷程度crypto/rand.Read
源为您的种子。 它会给你,你很可能希望在您的随机数(即使实际的实现本身是有限的一组独特的和确定性随机序列)不确定性的质量。
import (
crypto_rand "crypto/rand"
"encoding/binary"
math_rand "math/rand"
)
func init() {
var b [8]byte
_, err := crypto_rand.Read(b[:])
if err != nil {
panic("cannot seed math/rand package with cryptographically secure random number generator")
}
math_rand.Seed(int64(binary.LittleEndian.Uint64(b[:])))
}
作为一个方面说明,但相对于你的问题。 你可以创建自己的rand.Source
使用这种方法,以避免锁保护源的成本。 的rand
包效用函数是便利的,但它们也使用锁罩下以防止源被同时使用。 如果你不需要,你可以通过创建自己的避免它Source
和使用,在非同步的方式。 无论如何,你不应该进行补种迭代之间的随机数发生器,它从未被设计用来这种方式。
这是纳米秒,什么都得到相同的种子两次的机会。
无论如何,感谢您的帮助,这里是一个基于所有输入我的最终解决方案。
package main
import (
"math/rand"
"time"
)
func init() {
rand.Seed(time.Now().UTC().UnixNano())
}
// generates a random string
func srand(min, max int, readable bool) string {
var length int
var char string
if min < max {
length = min + rand.Intn(max-min)
} else {
length = min
}
if readable == false {
char = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
} else {
char = "ABCDEFHJLMNQRTUVWXYZabcefghijkmnopqrtuvwxyz23479"
}
buf := make([]byte, length)
for i := 0; i < length; i++ {
buf[i] = char[rand.Intn(len(char)-1)]
}
return string(buf)
}
// For testing only
func main() {
println(srand(5, 5, true))
println(srand(5, 5, true))
println(srand(5, 5, true))
println(srand(5, 5, false))
println(srand(5, 7, true))
println(srand(5, 10, false))
println(srand(5, 50, true))
println(srand(5, 10, false))
println(srand(5, 50, true))
println(srand(5, 10, false))
println(srand(5, 50, true))
println(srand(5, 10, false))
println(srand(5, 50, true))
println(srand(5, 4, true))
println(srand(5, 400, true))
println(srand(6, 5, true))
println(srand(6, 5, true))
println(srand(6, 5, true))
println(srand(6, 5, true))
println(srand(6, 5, true))
println(srand(6, 5, true))
println(srand(6, 5, true))
println(srand(6, 5, true))
println(srand(6, 5, true))
println(srand(6, 5, true))
println(srand(6, 5, true))
println(srand(6, 5, true))
}
如果你的目标只是产生随机数的刺痛话,我认为这是没有必要将其与多个函数调用或重置种子每次复杂化。
最重要的一步是实际运行之前调用函数的种子只有一次rand.Init(x)
种子使用所提供的种子值来初始化缺省源来确定的状态。 因此,这将是建议的实际函数调用伪随机数生成器之前调用它一次。
下面是一个示例代码创建一个随机数串
package main
import (
"fmt"
"math/rand"
"time"
)
func main(){
rand.Seed(time.Now().UnixNano())
var s string
for i:=0;i<10;i++{
s+=fmt.Sprintf("%d ",rand.Intn(7))
}
fmt.Printf(s)
}
我使用的原因sprintf的是,因为它允许简单的字符串格式化。
另外,在rand.Intn(7)
内置内置返回,作为int,在[0,7)一个非负的伪随机数。