生日悖论
生日悖论是指在不少于 23 个人中至少有两人生日相同的概率大于 50%。
例如:
在一个 30 人的小学班级中,存在两人生日相同的概率为 70%。
对于 60 人的大班,这种概率要大于 99%。
从引起逻辑矛盾的角度来说,生日悖论是一种 “佯谬”。但这个数学事实十分反直觉,故称之为一个悖论。生日悖论的数学理论被应用于设计密码学攻击方法——生日攻击。
代码实现
package main
import (
"crypto/rand"
"fmt"
"math/big"
"strconv"
)
func main() {
var count int64
var sample = 10000
var rate float64
var sampleRange int64
sampleRange = 365 //一年365天,生日的范围是1-365中的一天
count = match(sampleRange,sample) //计算实验中的重复次数
fmt.Printf("count = %d\n",count)
rate = (float64(count)/float64(sample))*100
fmt.Printf("rate is %f%\n",rate)
}
func match(Range int64 ,sample int) int64 { //把t和试验次数传进参数
var count int64 = 0 //计重复次数
var nums [23]int
for i := 0; i < sample; i++ {//重复统计
nums = Rond(Range)//生成随机数组
//开始判断是否有相同的数,相同则记一次
if containsDuplicate(nums) == true{
count += 1
}
}
return count
}
func Rond(Range int64) [23]int{//随机生成23个人
var arr[23] int
for i := 0; i < 23; i++{
result, _ := rand.Int(rand.Reader, big.NewInt(Range))
number := result.String()
fmt.Println(number)//打印随机生成的
num, err := strconv.Atoi(number)
if err == nil{
fmt.Printf(" ")
}
arr[i] = num
}
return arr
}
func containsDuplicate(num [23]int) bool {//判断是否冲突,即生日相同的一天
set := map[int]struct{}{}
for _ , v := range num {
if _, has := set[v]; has {
return true
}
set[v] = struct{}{}
}
return false
}
结果
sample越多,测试结果越准确,类似于抛硬币次数越多,正面或反面的概率越接近0.5,结果如图: