1. Go中的随机数生成
在许多编程任务中,随机数的生成是不可或缺的。Go语言通过 math/rand
包提供了伪随机数生成方式。伪随机数由种子(seed)决定,如果种子相同,生成的数列也会相同。为了确保每次程序运行时产生不同的随机数,我们通常使用当前时间作为种子。
示例1:简单的随机数生成
package main
import (
"fmt"
"math/rand"
"time"
)
func random(min, max int) int {
return rand.Intn(max-min) + min
}
func main() {
rand.Seed(time.Now().Unix())
for i := 0; i < 5; i++ {
fmt.Println("生成的随机数:", random(0, 100))
}
}
上述程序使用了当前时间作为种子来生成0到100之间的5个随机数。输出结果每次都会不同。
示例2:通过命令行控制随机数生成
为了使程序更具灵活性,我们可以通过命令行传入参数来控制随机数的生成范围和数量,甚至可以指定种子来生成固定序列的伪随机数。
package main
import (
"fmt"
"math/rand"
"os"
"strconv"
"time"
)
func random(min, max int) int {
return rand.Intn(max-min) + min
}
func main() {
MIN := 0
MAX := 100
TOTAL := 10
SEED := time.Now().Unix()
arguments := os.Args
switch len(arguments) {
case 2:
MIN, _ = strconv.Atoi(arguments[1])
MAX = MIN + 100
case 3:
MIN, _ = strconv.Atoi(arguments[1])
MAX, _ = strconv.Atoi(arguments[2])
case 4:
MIN, _ = strconv.Atoi(arguments[1])
MAX, _ = strconv.Atoi(arguments[2])
TOTAL, _ = strconv.Atoi(arguments[3])
case 5:
MIN, _ = strconv.Atoi(arguments[1])
MAX, _ = strconv.Atoi(arguments[2])
TOTAL, _ = strconv.Atoi(arguments[3])
SEED, _ = strconv.ParseInt(arguments[4], 10, 64)
default:
fmt.Println("使用默认值")
}
rand.Seed(SEED)
for i := 0; i < TOTAL; i++ {
fmt.Printf("%d ", random(MIN, MAX))
}
fmt.Println()
}
通过不同的命令行参数,可以控制生成的随机数。例如:
$ go run randomNumbers.go 10 50 5
14 37 27 49 16
这段代码生成了5个在10到50之间的随机数。
2. 加密级别的随机数生成
在安全领域,生成密码时,伪随机数不足以提供安全性。Go提供了 crypto/rand
包来生成加密安全的随机数,它可以生成不可预测的随机序列。
示例3:生成加密安全的随机密码
package main
import (
"crypto/rand"
"encoding/base64"
"fmt"
"os"
"strconv"
)
func generateBytes(n int64) ([]byte, error) {
b := make([]byte, n)
_, err := rand.Read(b)
if err != nil {
return nil, err
}
return b, nil
}
func generatePass(s int64) (string, error) {
b, err := generateBytes(s)
return base64.URLEncoding.EncodeToString(b), err
}
func main() {
var LENGTH int64 = 8
arguments := os.Args
if len(arguments) == 2 {
LENGTH, _ = strconv.ParseInt(arguments[1], 10, 64)
}
myPass, err := generatePass(LENGTH)
if err != nil {
fmt.Println("生成密码失败:", err)
return
}
fmt.Println("生成的密码:", myPass[0:LENGTH])
}
运行程序后会生成一个随机密码,例如:
生成的密码: Zm9yQ29kZT==
3. 矩阵运算与生成
矩阵在图像处理、机器学习等领域中有广泛应用。我们可以利用Go语言生成随机矩阵,并进行矩阵加法、减法等运算。
示例4:生成随机矩阵并进行矩阵加法
package main
import (
"fmt"
"math/rand"
"time"
)
func generateMatrix(row, col int) [][]int {
matrix := make([][]int, row)
for i := range matrix {
matrix[i] = make([]int, col)
for j := range matrix[i] {
matrix[i][j] = rand.Intn(10)
}
}
return matrix
}
func addMatrices(m1, m2 [][]int) [][]int {
result := make([][]int, len(m1))
for i := range m1 {
result[i] = make([]int, len(m1[i]))
for j := range m1[i] {
result[i][j] = m1[i][j] + m2[i][j]
}
}
return result
}
func main() {
rand.Seed(time.Now().Unix())
m1 := generateMatrix(3, 3)
m2 := generateMatrix(3, 3)
fmt.Println("矩阵1:", m1)
fmt.Println("矩阵2:", m2)
result := addMatrices(m1, m2)
fmt.Println("矩阵加法结果:", result)
}
通过上述代码,您可以生成两个3x3的随机矩阵,并执行矩阵加法运算。
4. 数独验证程序
数独是一个流行的逻辑益智游戏,要求将1到9填入一个9x9的网格中,使每行、每列和每个3x3的子区域都包含不重复的数字。我们可以通过编写程序验证数独是否解得正确。
示例5:数独验证
package main
import (
"bufio"
"errors"
"fmt"
"os"
"strconv"
"strings"
)
func importFile(file string) ([][]int, error) {
var err error
var mySlice = make([][]int, 0)
f, err := os.Open(file)
if err != nil {
return nil, err
}
defer f.Close()
r := bufio.NewReader(f)
for {
line, err := r.ReadString('\n')
fields := strings.Fields(line)
temp := make([]int, 0)
for _, v := range fields {
n, err := strconv.Atoi(v)
if err != nil {
return nil, err
}
temp = append(temp, n)
}
if len(temp) != 0 {
mySlice = append(mySlice, temp)
}
if err != nil {
break
}
}
return mySlice, nil
}
func validPuzzle(sl [][]int) bool {
for i := 0; i <= 2; i++ {
for j := 0; j <= 2; j++ {
iEl := i * 3
jEl := j * 3
mySlice := []int{0, 0, 0, 0, 0, 0, 0, 0, 0}
for k := 0; k <= 2; k++ {
for m := 0; m <= 2; m++ {
bigI := iEl + k
bigJ := jEl + m
val := sl[bigI][bigJ]
if val > 0 && val < 10 {
if mySlice[val-1] == 1 {
fmt.Println("数字出现两次:", val)
return false
} else {
mySlice[val-1] = 1
}
} else {
fmt.Println("无效值:", val)
return false
}
}
}
}
}
for i := 0; i <= 8; i++ {
sum := 0
for j := 0; j <= 8; j++ {
sum = sum + sl[i][j]
}
if sum != 45 {
return false
}
sum = 0
}
for i :=
0; i <= 8; i++ {
sum := 0
for j := 0; j <= 8; j++ {
sum = sum + sl[j][i]
}
if sum != 45 {
return false
}
sum = 0
}
return true
}
func main() {
arguments := os.Args
if len(arguments) != 2 {
fmt.Printf("使用: loadFile 文件名\n")
return
}
file := arguments[1]
mySlice, err := importFile(file)
if err != nil {
fmt.Println(err)
return
}
if validPuzzle(mySlice) {
fmt.Println("数独正确!")
} else {
fmt.Println("数独错误!")
}
}
通过此程序,您可以从文件导入一个数独,并验证其是否解得正确。输入数独文件格式为9x9的数独矩阵,每行数字间以空格分隔。
运行程序:
$ go run sudoku.go valid_sudoku.txt
数独正确!
结论
通过本文的学习,读者不仅能掌握如何在Go语言中生成随机数,还能学会如何生成加密安全的随机数、矩阵运算以及数独验证等高级技术。Go语言为我们提供了丰富的工具,能轻松应对多种编程挑战。