Тест с множественным выбором имеет четыре возможных ответа на каждый из 16 вопросов. Студент угадывает ответ на каждый вопрос, поэтому вероятность получить правильный ответ на любой заданный вопрос составляет один к четырем, четверть, 1/4, 25% или фракция 0,25. Предполагают, что условия биномиального эксперимента выполнены: n = 16 вопросов составляют испытания; каждый вопрос приводит к одному из двух возможных исходов (правильному или неправильному); вероятность быть правильным равна 0,25 и постоянна, если не предполагается знание предмета; на вопросы отвечают независимо, если ответ студента на вопрос никоим образом не влияет на его ответ на другой вопрос.
Во-первых, мы должны иметь возможность использовать конструктор биномиального распределения (и, конечно, некоторые входные / выходные данные).
#include <boost/math/distributions/binomial.hpp>
using boost::math::binomial;
#include <iostream>
using std::cout; using std::endl;
using std::ios; using std::flush; using std::left; using std::right; using std::fixed;
#include <iomanip>
using std::setw; using std::setprecision;
#include <exception>
Число правильных ответов, X, распределено как биномиальная случайная величина с параметрами биномиального распределения: вопросы n и вероятность дроби успеха p. Итак, мы строим биномиальное распределение:
int questions = 16;
int answers = 4;
double success_fraction = 1. / answers;
binomial quiz(questions, success_fraction);
и отображать параметры распределения, которые мы использовали таким образом:
cout << "In a quiz with " << quiz.trials()
<< " questions and with a probability of guessing right of "
<< quiz.success_fraction() * 100 << " %"
<< " or 1 in " << static_cast<int>(1. / quiz.success_fraction()) << endl;
Покажите несколько вероятностей просто угадывания:
cout << "Probability of getting none right is " << pdf(quiz, 0) << endl;
cout << "Probability of getting exactly one right is " << pdf(quiz, 1) << endl;
cout << "Probability of getting exactly two right is " << pdf(quiz, 2) << endl;
int pass_score = 11;
cout << "Probability of getting exactly " << pass_score << " answers right by chance is "
<< pdf(quiz, pass_score) << endl;
cout << "Probability of getting all " << questions << " answers right by chance is "
<< pdf(quiz, questions) << endl;
Probability of getting none right is 0.0100226
Probability of getting exactly one right is 0.0534538
Probability of getting exactly two right is 0.133635
Probability of getting exactly 11 right is 0.000247132
Probability of getting exactly all 16 answers right by chance is 2.32831e-010
Они не дают никакого поощрения гадалкам!
Мы можем вычислить вероятность «получить абсолютно правильно» ( == ) таким образом:
cout << "\n" "Guessed Probability" << right << endl;
for (int successes = 0; successes <= questions; successes++)
{
double probability = pdf(quiz, successes);
cout << setw(2) << successes << " " << probability << endl;
}
cout << endl;
Guessed Probability
0 0.0100226
1 0.0534538
2 0.133635
3 0.207876
4 0.225199
5 0.180159
6 0.110097
7 0.0524273
8 0.0196602
9 0.00582526
10 0.00135923
11 0.000247132
12 3.43239e-005
13 3.5204e-006
14 2.51457e-007
15 1.11759e-008
16 2.32831e-010
Затем мы можем добавить вероятности некоторого «точно правильного» типа:
cout << "Probability of getting none or one right is " << pdf(quiz, 0) + pdf(quiz, 1) << endl;
Probability of getting none or one right is 0.0634764
Но если задействовано более пары баллов, удобнее (и может быть точнее) использовать вместо этого функцию кумулятивного распределения (cdf):
cout << "Probability of getting none or one right is " << cdf(quiz, 1) << endl;
Probability of getting none or one right is 0.0634764
Поскольку cdf является инклюзивным, мы можем получить вероятность до 10 правых.
cout << "Probability of getting <= 10 right (to fail) is " << cdf(quiz, 10) << endl;
Probability of getting <= 10 right (to fail) is 0.999715
Чтобы получить вероятность получить 11 или более прав (пройти), заманчиво использовать
1 - cdf(quiz, 10)
Вероятность возникновения >10
cout << "Probability of getting > 10 right (to pass) is " << 1 - cdf(quiz, 10) << endl;
Probability of getting > 10 right (to pass) is 0.000285239
Но этому следует противостоять в пользу использованиякомплементов.функция (см.Почему комплементы?.
cout << "Probability of getting > 10 right (to pass) is " << cdf(complement(quiz, 10)) << endl;
Probability of getting > 10 right (to pass) is 0.000285239
И мы можем проверить, что эти два,<= 10 и >10, складываются в единство.
BOOST_ASSERT((cdf(quiz, 10) + cdf(complement(quiz, 10))) == 1.);
Если мы хотим тест, а не тест, потому что CDF включен, мы должны вычесть один из баллов.
cout << "Probability of getting less than " << pass_score
<< " (< " << pass_score << ") answers right by guessing is "
<< cdf(quiz, pass_score -1) << endl;
Probability of getting less than 11 (< 11) answers right by guessing is 0.999715
Точно так же, чтобы получить >=, а не >тест, нам также нужно вычесть один из баллов (и снова проверить сумму - единство). Это потому, что если cdfвключительно, то его дополнение должно бытьисключительным, иначе был бы один возможный результат, подсчитанный дважды!
cout << "Probability of getting at least " << pass_score
<< "(>= " << pass_score << ") answers right by guessing is "
<< cdf(complement(quiz, pass_score-1))
<< ", only 1 in " << 1/cdf(complement(quiz, pass_score-1)) << endl;
BOOST_ASSERT((cdf(quiz, pass_score -1) + cdf(complement(quiz, pass_score-1))) == 1);
Probability of getting at least 11 (>= 11) answers right by guessing is 0.000285239, only 1 in 3505.83
Наконец, мы можем сформулировать некоторые вероятности:
cout << "\n" "At most (<=)""\n""Guessed OK Probability" << right << endl;
for (int score = 0; score <= questions; score++)
{
cout << setw(2) << score << " " << setprecision(10)
<< cdf(quiz, score) << endl;
}
cout << endl;
At most (<=)
Guessed OK Probability
0 0.01002259576
1 0.0634764398
2 0.1971110499
3 0.4049871101
4 0.6301861752
5 0.8103454274
6 0.9204427481
7 0.9728700437
8 0.9925302796
9 0.9983555346
10 0.9997147608
11 0.9999618928
12 0.9999962167
13 0.9999997371
14 0.9999999886
15 0.9999999998
16 1
cout << "\n" "At least (>)""\n""Guessed OK Probability" << right << endl;
for (int score = 0; score <= questions; score++)
{
cout << setw(2) << score << " " << setprecision(10)
<< cdf(complement(quiz, score)) << endl;
}
At least (>)
Guessed OK Probability
0 0.9899774042
1 0.9365235602
2 0.8028889501
3 0.5950128899
4 0.3698138248
5 0.1896545726
6 0.07955725188
7 0.02712995629
8 0.00746972044
9 0.001644465374
10 0.0002852391917
11 3.810715862e-005
12 3.783265129e-006
13 2.628657967e-007
14 1.140870154e-008
15 2.328306437e-010
16 0
Теперь мы рассмотрим вероятностидиапазоновправильных догадок.
Во-первых, вычислите вероятность правильного получения диапазона догадок, добавляя точные вероятности каждой из них с низкого ... высокого.
int low = 3;
int high = 5;
double sum = 0.;
for (int i = low; i <= high; i++)
{
sum += pdf(quiz, i);
}
cout.precision(4);
cout << "Probability of getting between "
<< low << " and " << high << " answers right by guessing is "
<< sum << endl;
Probability of getting between 3 and 5 answers right by guessing is 0.6132
Или, как правило, лучше, мы можем вместо этого использовать разницу в Cdfs:
cout << "Probability of getting between " << low << " and " << high << " answers right by guessing is "
<< cdf(quiz, high) - cdf(quiz, low - 1) << endl;
Probability of getting between 3 and 5 answers right by guessing is 0.6132
Мы также можем попробовать несколько комбинаций высокого и низкого выбора:
low = 1; high = 6;
cout << "Probability of getting between " << low << " and " << high << " answers right by guessing is "
<< cdf(quiz, high) - cdf(quiz, low - 1) << endl;
low = 1; high = 8;
cout << "Probability of getting between " << low << " and " << high << " answers right by guessing is "
<< cdf(quiz, high) - cdf(quiz, low - 1) << endl;
low = 4; high = 4;
cout << "Probability of getting between " << low << " and " << high << " answers right by guessing is "
<< cdf(quiz, high) - cdf(quiz, low - 1) << endl;
Probability of getting between 1 and 6 answers right by guessing is 0.9104
Probability of getting between 1 and 8 answers right by guessing is 0.9825
Probability of getting between 4 and 4 answers right by guessing is 0.2252
Используя моменты распределения, можно сказать больше о распространении результатов от угадывания.
cout << "By guessing, on average, one can expect to get " << mean(quiz) << " correct answers." << endl;
cout << "Standard deviation is " << standard_deviation(quiz) << endl;
cout << "So about 2/3 will lie within 1 standard deviation and get between "
<< ceil(mean(quiz) - standard_deviation(quiz)) << " and "
<< floor(mean(quiz) + standard_deviation(quiz)) << " correct." << endl;
cout << "Mode (the most frequent) is " << mode(quiz) << endl;
cout << "Skewness is " << skewness(quiz) << endl;
By guessing, on average, one can expect to get 4 correct answers.
Standard deviation is 1.732
So about 2/3 will lie within 1 standard deviation and get between 3 and 5 correct.
Mode (the most frequent) is 4
Skewness is 0.2887
Квантили (проценты или процентные точки) для нескольких уровней вероятности:
cout << "Quartiles " << quantile(quiz, 0.25) << " to "
<< quantile(complement(quiz, 0.25)) << endl;
cout << "1 standard deviation " << quantile(quiz, 0.33) << " to "
<< quantile(quiz, 0.67) << endl;
cout << "Deciles " << quantile(quiz, 0.1) << " to "
<< quantile(complement(quiz, 0.1))<< endl;
cout << "5 to 95% " << quantile(quiz, 0.05) << " to "
<< quantile(complement(quiz, 0.05))<< endl;
cout << "2.5 to 97.5% " << quantile(quiz, 0.025) << " to "
<< quantile(complement(quiz, 0.025)) << endl;
cout << "2 to 98% " << quantile(quiz, 0.02) << " to "
<< quantile(complement(quiz, 0.02)) << endl;
cout << "If guessing then percentiles 1 to 99% will get " << quantile(quiz, 0.01)
<< " to " << quantile(complement(quiz, 0.01)) << " right." << endl;
Обратите внимание, что эти выходные интегральные значения, поскольку политика по умолчанию являетсяinteger_round_outwards
.
Quartiles 2 to 5
1 standard deviation 2 to 5
Deciles 1 to 6
5 to 95% 0 to 7
2.5 to 97.5% 0 to 8
2 to 98% 0 to 8
Ценности квантилей контролируютсяпониманием дискретных квантилейвыбранной политики квантиля. По умолчаниюinteger_round_outwards
, поэтому нижний квантиль округляется вниз, а верхний квантиль округляется.
Но мы можем верить, что реальные значения говорят нам немного больше — см.дискретные функции.
Мы можем контролировать политику длявсехраспределений.
#define BOOST_MATH_DISCRETE_QUANTILE_POLICY real
at the head of the program would make this policy apply
, и только, единица перевода.
Или мы можем теперь создать политику, которая имеет дискретный квантиль (здесь избегая любых заявлений об использовании пространств имен).
using boost::math::policies::policy;
using boost::math::policies::discrete_quantile;
using boost::math::policies::real;
using boost::math::policies::integer_round_outwards;
typedef boost::math::policies::policy<discrete_quantile<real> > real_quantile_policy;
Добавить пользовательское биномиальное распределение, называемое
real_quantile_binomial
который использует
real_quantile_policy
using boost::math::binomial_distribution;
typedef binomial_distribution<double, real_quantile_policy> real_quantile_binomial;
Постройте объект этого пользовательского распределения:
real_quantile_binomial quiz_real(questions, success_fraction);
Используйте это, чтобы показать некоторые квантили, которые теперь имеют реальные, а не целые значения.
cout << "Quartiles " << quantile(quiz, 0.25) << " to "
<< quantile(complement(quiz_real, 0.25)) << endl;
cout << "1 standard deviation " << quantile(quiz_real, 0.33) << " to "
<< quantile(quiz_real, 0.67) << endl;
cout << "Deciles " << quantile(quiz_real, 0.1) << " to "
<< quantile(complement(quiz_real, 0.1))<< endl;
cout << "5 to 95% " << quantile(quiz_real, 0.05) << " to "
<< quantile(complement(quiz_real, 0.05))<< endl;
cout << "2.5 to 97.5% " << quantile(quiz_real, 0.025) << " to "
<< quantile(complement(quiz_real, 0.025)) << endl;
cout << "2 to 98% " << quantile(quiz_real, 0.02) << " to "
<< quantile(complement(quiz_real, 0.02)) << endl;
cout << "If guessing, then percentiles 1 to 99% will get " << quantile(quiz_real, 0.01)
<< " to " << quantile(complement(quiz_real, 0.01)) << " right." << endl;
Real Quantiles
Quartiles 2 to 4.621
1 standard deviation 2.665 to 4.194
Deciles 1.349 to 5.758
5 to 95% 0.8374 to 6.456
2.5 to 97.5% 0.4281 to 7.069
2 to 98% 0.3131 to 7.252
If guessing then percentiles 1 to 99% will get 0 to 7.788 right.
binomial_quiz_example.cppдля полного исходного кода и вывода.