我想在一行0 to 9
范围内生成3个随机数,这些数字应该总计给定的固定数。例如,对于给定的固定和15,一种可能的解决方案是(3, 8, 4)
。我怎样才能做到这一点 ?感谢。
答案 0 :(得分:3)
a,b,c
和0
1
sum
a,b,c
a,b,c
除以sum
a,b,c
给定所需的求和整数,然后将a,b,c
舍入为最接近的整数sum(a, b, c) == given integer ? get result : try again
使用boost随机生成器:
#include <iostream>
#include <time.h>
#include <iomanip>
#include <boost/random.hpp>
int main()
{
static time_t seed = time(0);
boost::random::mt19937 RandomNumGen(seed++);
boost::random::uniform_real_distribution<> Range(0, 1);
int Desired_Integer = 15;
int Rand_Max = 9;
int Max_Itr = 100000000;
int Count = 0;
int SumABC[3][10] = { 0 };
float bias = 0.5;
float a, b, c;
for (int Loop = 1; Loop <= Max_Itr; ++Loop)
{
a = Range(RandomNumGen);
b = Range(RandomNumGen);
c = Range(RandomNumGen);
float Sum = a + b + c;
a = a / Sum;
b = b / Sum;
c = c / Sum;
//Round to the nearest integer;
int aI = static_cast<int>(a * Desired_Integer + bias), bI = static_cast<int>(b * Desired_Integer + bias), cI = static_cast<int>(c * Desired_Integer + bias);
if (aI <= Rand_Max && bI <= Rand_Max && cI <= Rand_Max && aI + bI + cI == Desired_Integer)
{
SumABC[0][aI]++;
SumABC[1][bI]++;
SumABC[2][cI]++;
Count++;
}
}
int PaddingWidth = 10;
std::cout << "\n" << Count << " in " << Max_Itr << " loops get desired outcome. \nDistribution of a,b,c: \n";
std::cout << "Number" << std::setw(PaddingWidth) << "a" << std::setw(PaddingWidth) << "b" << std::setw(PaddingWidth) << "c" << std::endl;
for (int i = 0; i < 10; i++)
{
std::cout
<< i << std::setw(PaddingWidth + 8)
<< std::setprecision(4) << 100.0 * SumABC[0][i] / (float)Count << std::setw(PaddingWidth)
<< std::setprecision(4) << 100.0 * SumABC[1][i] / (float)Count << std::setw(PaddingWidth)
<< std::setprecision(4) << 100.0 * SumABC[2][i] / (float)Count << std::endl;
}
std::cout << "\n\n";
system("pause");
return 0;
}
答案 1 :(得分:2)
在处理随机变量时,检查工作是个不错的主意。
我模拟了两个答案。小涛不仅分布不同,而且分配频率也不同。 aI和bI具有相同的分布,但cI明显不同。这三个应该有相同的分布。
此外,Kay的解决方案具有正确的分布,因为P(a)== 1 s / b 1.25倍P(a)== 1.
这是一个确定性的解决方案,它与Kay的统计数据完全相同
此外,纯粹从0到9的概率POV看每个数字的出现频率是4 / 73,5 /73,6 / 73,7 / 73,8 / 73,9 / 73,10 / 73,9 / 73,8 / 73和7/73
创建总和为15的所有可能数字序列的向量。然后随机选择一个元素。每个数字集具有相同的被选择概率
#include <algorithm>
#include <array>
#include <iostream>
#include <numeric>
#include <random>
using namespace std;
// Your constants:
static constexpr unsigned DICE_COUNT = 3;
static constexpr unsigned DICE_SIDES = 10;
static constexpr unsigned DESIRED_NUMBER = 15;
int main() {
// Initialize your PRNG:
vector<array<int, 3>> allLegalNumbers;
for (int i=0; i <= 9; i++) // go through all possible sets of 3 numbers from 0 to 9
for (int ii = 0; ii < DICE_SIDES; ii++)
for (int iii = 0; iii < DICE_SIDES; iii++)
if (i + ii + iii == DESIRED_NUMBER) // keep the ones that add up to 15
allLegalNumbers.push_back(array<int, 3> {i, ii, iii});
random_device rd;
mt19937 generator(rd());
uniform_int_distribution<unsigned> distribution(0, allLegalNumbers.size() - 1);
int sum[3][DICE_SIDES]{};
int sum_count = 0;
for (int Loop = 1; Loop < 100000000; ++Loop)
{
auto index = distribution(generator);
sum[0][allLegalNumbers[index][0]]++;
sum[1][allLegalNumbers[index][1]]++;
sum[2][allLegalNumbers[index][2]]++;
sum_count++;
}
for (int i = 0; i < DICE_SIDES; i++)
printf("Percent of aI==%d:%5.2f bI==%d:%5.2f cI==%d:%5.2f\n",
i, 100.0*sum[0][i] / sum_count,
i, 100.0*sum[1][i] / sum_count,
i, 100.0*sum[2][i] / sum_count);
return 0;
}
/* Results:
Percent of aI==0: 5.48 bI==0: 5.48 cI==0: 5.48
Percent of aI==1: 6.85 bI==1: 6.85 cI==1: 6.85
Percent of aI==2: 8.22 bI==2: 8.22 cI==2: 8.22
Percent of aI==3: 9.59 bI==3: 9.59 cI==3: 9.59
Percent of aI==4:10.96 bI==4:10.96 cI==4:10.96
Percent of aI==5:12.33 bI==5:12.33 cI==5:12.34
Percent of aI==6:13.69 bI==6:13.70 cI==6:13.70
Percent of aI==7:12.34 bI==7:12.33 cI==7:12.33
Percent of aI==8:10.96 bI==8:10.96 cI==8:10.95
Percent of aI==9: 9.59 bI==9: 9.59 cI==9: 9.58
*/
小涛的回答模拟:注意cI v aI和bI的不同分布
#include <iostream>
int main()
{
int SumI = 15;
int Rand_Max = 9;
float a, b, c;
int sum[3][10]{};
int sum_count = 0;
for (int Loop = 1; Loop < 100000000; ++Loop)
{
a = static_cast<float>(rand() % Rand_Max) / static_cast<float>(Rand_Max);
b = static_cast<float>(rand() % Rand_Max) / static_cast<float>(Rand_Max);
c = static_cast<float>(rand() % Rand_Max) / static_cast<float>(Rand_Max);
float Sum = a + b + c;
a = a / Sum;
b = b / Sum;
c = c / Sum;
//Round to the nearest integer;
int aI = static_cast<int>(a * SumI + 0.5), bI = static_cast<int>(b * SumI + 0.5), cI = static_cast<int>(c * SumI + 0.5);
if (aI <= Rand_Max && bI <= Rand_Max && cI <= Rand_Max && aI + bI + cI == SumI)
{
sum[0][aI]++;
sum[1][bI]++;
sum[2][cI]++;
sum_count++;
}
}
for (int i = 0; i < 10; i++)
printf("Percent of aI==%d:%5.2f bI==%d:%5.2f cI==%d:%5.2f\n",
i, 100.0*sum[0][i] / sum_count,
i, 100.0*sum[1][i] / sum_count,
i, 100.0*sum[2][i] / sum_count);
return 0;
}
/* Results:
Percent of aI==0: 5.84 bI==0: 5.83 cI==0: 5.84
Percent of aI==1: 5.30 bI==1: 5.31 cI==1: 5.31
Percent of aI==2: 7.43 bI==2: 7.43 cI==2: 6.90
Percent of aI==3: 9.55 bI==3: 9.54 cI==3: 9.28
Percent of aI==4:10.61 bI==4:10.61 cI==4:10.60
Percent of aI==5:15.64 bI==5:15.66 cI==5:15.39
Percent of aI==6:16.18 bI==6:16.18 cI==6:17.51
Percent of aI==7:11.41 bI==7:11.40 cI==7:10.88
Percent of aI==8: 9.82 bI==8: 9.81 cI==8:10.08
Percent of aI==9: 8.22 bI==9: 8.22 cI==9: 8.22
*/
凯的回答没有出现这个错误。这是模拟:
#include <algorithm>
#include <array>
#include <iostream>
#include <numeric>
#include <random>
// Don't use "using namespace" in production.
// I only use it to avoid the horizontal scrollbar.
using namespace std;
// Your constants:
static constexpr unsigned DICE_COUNT = 3;
static constexpr unsigned DICE_SIDES = 10;
static constexpr unsigned DESIRED_NUMBER = 15;
int main() {
// Initialize your PRNG:
random_device rd;
mt19937 generator(rd());
uniform_int_distribution<unsigned> distribution(0, DICE_SIDES - 1);
int sum[3][10]{};
int sum_count = 0;
for (int Loop = 1; Loop < 10000000; ++Loop)
{
// Fill the array with three random numbers until you have a match:
array<unsigned, DICE_COUNT> values = { 0 };
while (accumulate(begin(values), end(values), 0) != DESIRED_NUMBER) {
for_each(begin(values), end(values), [&](unsigned &v) {
v = distribution(generator);
//v = rand() % DICE_SIDES; // substitute this to use rand()
});
}
sum[0][values[0]]++;
sum[1][values[1]]++;
sum[2][values[2]]++;
sum_count++;
}
for (int i = 0; i < 10; i++)
printf("Percent of aI==%d:%5.2f bI==%d:%5.2f cI==%d:%5.2f\n",
i, 100.0*sum[0][i] / sum_count,
i, 100.0*sum[1][i] / sum_count,
i, 100.0*sum[2][i] / sum_count);
return 0;
}
/* Results:
Percent of aI==0: 5.48 bI==0: 5.48 cI==0: 5.47
Percent of aI==1: 6.85 bI==1: 6.85 cI==1: 6.85
Percent of aI==2: 8.22 bI==2: 8.19 cI==2: 8.22
Percent of aI==3: 9.60 bI==3: 9.59 cI==3: 9.60
Percent of aI==4:10.97 bI==4:10.96 cI==4:10.99
Percent of aI==5:12.34 bI==5:12.32 cI==5:12.32
Percent of aI==6:13.69 bI==6:13.70 cI==6:13.71
Percent of aI==7:12.31 bI==7:12.34 cI==7:12.30
Percent of aI==8:10.95 bI==8:10.96 cI==8:10.95
Percent of aI==9: 9.60 bI==9: 9.60 cI==9: 9.59
*/
答案 2 :(得分:1)
这是一个如何在C ++ 11中生成随机数的教程:http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution
最简单的解决方案是尝试直到找到匹配项:
#include <algorithm>
#include <array>
#include <iostream>
#include <numeric>
#include <random>
// Don't use "using namespace" in production.
// I only use it to avoid the horizontal scrollbar.
using namespace std;
// Your constants:
static constexpr unsigned DICE_COUNT = 3;
static constexpr unsigned DICE_SIDES = 10;
static constexpr unsigned DESIRED_NUMBER = 15;
int main() {
// Initialize your PRNG:
random_device rd;
mt19937 generator(rd());
uniform_int_distribution<unsigned> distribution(0, DICE_SIDES - 1);
// Fill the array with three random numbers until you have a match:
array<unsigned, DICE_COUNT> values = { 0 };
while (accumulate(begin(values), end(values), 0) != DESIRED_NUMBER) {
for_each(begin(values), end(values), [&](unsigned &v) {
v = distribution(generator);
});
}
// Print the result:
for_each(begin(values), end(values), [&](unsigned &v) {
cout << v << ' ';
});
cout << endl;
return 0;
}
你需要大约9次迭代才能获得50/50的机会,你将投掷15: