关于骰子概率计算的一个C++问题

A C++ question about dice probability calculation

本文关键字:一个 C++ 问题 于骰 概率 计算      更新时间:2023-10-16

编写一个程序来找出每个概率 "总值"当几个无偏的不规则骰子(可能具有不同数量的 面孔(同时被抛出。

当掷出无偏骰子时,具有不同面值的概率应该 等同。例如,一个典型的立方骰子应该给出 1/6 的概率 值 1、2、3、4、5 和 6。 如果抛出两个立方骰子,则两个骰子上的面值之和在范围内 [2..12]但是,每个"总值"的概率并不相等。例如, 总计 4 的概率为 3/36(对于组合 1+3、2+2 和 3+3(,而 总共 2 的概率只有 1/36(当两个骰子都给出 1 时(。

Sample output as follow: (the one with * are the input from user)
Input the number of dice(s): *2
Input the number of faces for the 1st dice: *6
Input the number of faces for the 2nd dice: *6
Probability of 2 = 1/36
Probability of 3 = 2/36
Probability of 4 = 3/36
Probability of 5 = 4/36
Probability of 6 = 5/36
Probability of 7 = 6/36
Probability of 8 = 5/36
Probability of 9 = 4/36
Probability of 10 = 3/36
Probability of 11 = 2/36
Probability of 12 = 1/36
Input the number of dice(s): *5
Input the number of faces for the 1st dice: *1
Input the number of faces for the 2nd dice: *2
Input the number of faces for the 3rd dice: *3
Input the number of faces for the 4th dice: *4
Input the number of faces for the 5th dice: *5
Probability of 5 = 1/120
Probability of 6 = 4/120
Probability of 7 = 9/120
Probability of 8 = 15/120
Probability of 9 = 20/120
Probability of 10 = 22/120
Probability of 11 = 20/120
Probability of 12 = 15/120
Probability of 13 = 9/120
Probability of 14 = 4/120
Probability of 15 = 1/120

我实际上不知道如何完成概率部分。我想有一些关于计算问题的方法的提示。

#include <iostream>
#include <string>
using namespace std;
//Initialise output function
string output(int num){
case 1:
return "st";
break;
case 2:
return "nd";
break;
case 3:
return "rd";
break;
default:
return "th";
}

//Roll function
int roll(int num, int result, int value[20]){
int dice[num][20];
for (int i=0; i<num;i++){
for (int j=1; j<=value[i];j++){
for (int k=0; k<value[i];k++)
dice[i][k]=j;
}
}
}
}
int main(){
int number;
//Initialise the number variable
cout <<"Input the number of dice(s): ";
cin >> number;
cout<<endl;
//Initialise the face of the dice using std::array
int value[11];
for (int i=0; i<number; i++){
cout << "Input the number of faces for the "<< i+1 << output(i+1) 
<<" dice: ";
cin>>value[i];
}
//set the base of the probability (multiply), the maxrange (sum) for 
the dice probability
int base=1;
int sum;
for (int i=0; i<number; i++){
base = base*value[i];
sum = sum +value[i];
}
//Output statements
if (sum >9){
for (int i=number; i<10; i++){
cout << "Probability of  "<<i<<" = "<<roll(number, i, value);
}
for (int i=10; i<=sum;i++){
cout << "Probability of "<<i<<" = "<<roll(number, i, value);
}
} else {
for (int i=number; i<=sum; i++){
cout << "Probability of "<<i<<" = "<<roll(number, i, value);
}
}
return 0;
}

您可以使用 brute froce 并使用递归函数计算所有组合,并使用映射来计算每个结果出现的数量。

此外,使用 C++ 容器而不是 C 样式数组。

喜欢:

#include <iostream>
#include <vector>
#include <map>
void calcAll(const uint32_t value,
const uint32_t index, 
const std::vector<uint32_t>& dices, 
std::map<uint32_t, uint32_t>& count, 
uint32_t& total)
{
if (index == dices.size())
{
// No more dices -> save result and stop recursion
auto it = count.find(value);
if (it == count.end())
{
count[value]=1;
}
else
{
count[value]++;
}
++total;
return;
}
// Iterate over all dice values
for (uint32_t i = 0; i < dices[index]; ++i)
{
calcAll(value + i + 1, index + 1, dices, count, total);
}
}
int main() {
std::vector<uint32_t> dices {6, 6, 6}; // 3 dices, 6 sides each
std::map<uint32_t, uint32_t> count;
uint32_t total = 0;   
calcAll(0, 0, dices, count, total);
for (const auto& v : count)
{
std::cout << v.first << " seen " << v.second << " times out of " << total << std::endl;
}
return 0;
}

输出:

3 seen 1 times out of 216
4 seen 3 times out of 216
5 seen 6 times out of 216
6 seen 10 times out of 216
7 seen 15 times out of 216
8 seen 21 times out of 216
9 seen 25 times out of 216
10 seen 27 times out of 216
11 seen 27 times out of 216
12 seen 25 times out of 216
13 seen 21 times out of 216
14 seen 15 times out of 216
15 seen 10 times out of 216
16 seen 6 times out of 216
17 seen 3 times out of 216
18 seen 1 times out of 216
对于 6 面骰子,您有一个"概率向量">

[1/6, 1/6, 1/6, 1/6, 1/6, 1/6]然后对于每个额外的骰子,您将向量与下一个骰子的"概率向量"进行卷积,以获得更长、更"钟形"的向量。

[1/6, 1/6, 1/6, 1/6, 1/6, 1/6] * [1/6, 1/6, 1/6, 1/6, 1/6, 1/6] =
[1/36, 2/36, 3/36, 4/36, 5/36, 6/36, 5/36, 4/36, 3/36, 2/36, 1/36]

你可以这样编码:(请注意,我从卷积中分解了分母(。

static std::vector<int> conv(const std::vector<int>& f, const std::vector<int>& g) {
const int nf = f.size();
const int ng = g.size();
const int n  = nf + ng - 1;
std::vector<int> out(n);
for(int i = 0; i < n; ++i) {
const int jmn = (i >= ng - 1) ? i - (ng - 1) : 0;
const int jmx = (i <  nf - 1) ? i            : nf - 1;
for(int j = jmn; j <= jmx; ++j) {
out[i] += (f[j] * g[i - j]);
}
}
return out; 
}
static void rollDice(const std::vector<int>& dice) {
std::vector<int> firstDie(dice[0], 1);
std::vector<int> a = firstDie;
int denominator = dice[0];
for (int i = 1; i < dice.size(); ++i) {
a = conv(a, std::vector<int>(dice[i], 1));
denominator *= dice[i];
}
for (auto aa : a) {
std::cout << aa << '/' << denominator << 'n';
}
}
int main() {
rollDice({6, 6});
rollDice({1, 2, 3, 4, 5});
}

输出为:

1/36
2/36
3/36
4/36
5/36
6/36
5/36
4/36
3/36
2/36
1/36
1/120
4/120
9/120
15/120
20/120
22/120
20/120
15/120
9/120
4/120
1/120