2 min read

从0~1之间任选3个数, 其能构成三角形的概率有多大?

有一个有趣的问题:

从 0~1 之间任选3个数, 这三个数能构成三角形的概率有多大?

用 R 来实现一下。

1
2
3
4
5
# R version
version$platform
## [1] "x86_64-apple-darwin17.0"
version$version.string
## [1] "R version 4.1.2 (2021-11-01)"

整体思路是利用古典概率模型,把算概率的问题转化为求解目标事件发生频率的问题,用多次试验得到的这个频率来近似概率值。

主函数是 prob.tri(),输入是总试验次数n (默认值为 10000),只需要获得能构成三角形的次数 total,则频率 f = total / n, 此即为该函数的输出。

对于每一次实验,进行如下步骤:

  1. 先假设能成功,设置标识 is_tri 为1(表示能成功)
  2. 随机生成3个数(runif 均匀分布),用来作为三个边
  3. 根据构成三角形的条件两边之和大于第三边,对 3 种情况都进行验证(a+b>c, b+c>a, c+a>b), 共循环3次
  4. 如果验证失败,在改标志 is_tri 为0; 如果验证成功,则给 total加 1, 表示成功次数累加
  5. 进行完指定次数的试验,输出频率值并结束

最后,在得到 total 值后,即可计算频率值。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# triangle problem
prob.tri <- function(n = 10000) {
  total <- 0 # total trial times
  j <- 0 # loop index

  while (j <= n) {
    # flag: `is.tri = 1` means it can be a triangle
    is.tri <- 1

    # select 3 random number from uniform-distribution
    vec <- runif(3)

    # to tell if it's possible to form a triangle
    # (a+b>c, b+c>a, c+a>b)
    for (i in 1:3) {
      if (vec[i] > sum(vec[-i])) {
        is.tri <- 0
      }
    }
    total <- total + is.tri
    j <- j + 1
  }
  # calculation of probability of successful triangles
  total / n
}

# 进行 10 轮试验,看看结果的分布情况
mult.result <- c()
for (i in 1:10) {
  mult.result <- rbind(mult.result, prob.tri())
}
print(mult.result)
##         [,1]
##  [1,] 0.5003
##  [2,] 0.4987
##  [3,] 0.5073
##  [4,] 0.4940
##  [5,] 0.5047
##  [6,] 0.5026
##  [7,] 0.5040
##  [8,] 0.5067
##  [9,] 0.5048
## [10,] 0.4921

可以看到,结果在逼近于 0.5。我们对结果数据进行拟合,并画图展示。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
data <- mult.result[, 1]
df <- data.frame(x = 1:length(data), y = data)

# fitting
fit <- lm(y ~ x, data = df)

# custom y_ticks
y_ticks <- seq(0, 1, by = 0.1)

# plot: do not use default y_ticks
plot(df$x, df$y, pch = 16, col = "black",
  xlab = "Trial", ylab = "Frequency(Probability)",
  ylim = c(0, 1), yaxt = "n"
)
# set y_ticks
axis(side = 2, at = y_ticks)
abline(fit, col = "red")

根据上述 10 轮 10000 次试验的结果可知,最后能形成三角形的概率是 0.5.