комбинации — Расчет вероятности испытаний C ++ Бернулли

Программа запрашивает у пользователя количество раз, чтобы подбросить монету (n; количество испытаний).

Успех считается главой.

Безупречно, программа создает случайное число от 0 до 1. 0 считаются головами и успехом.

Затем программа должна вывести ожидаемые значения получения х количества головок. Например, если монета была перевернута 4 раза, каковы следующие вероятности, используя формулу

nCk * p^k * (1-p)^(n-k)
Expected 0 heads with n flips: xxx
Expected 1 heads with n flips: xxx
...
Expected n heads with n flips: xxx

Делая это с «большими» числами, цифры получаются странными значениями. Это происходит, если 15 или двадцать вводятся на входе. Я получаю 0 и отрицательные значения для значения, которое должно быть ххх.

Отладка, я заметил, что nCk оказался отрицательным и не правильным по отношению к верхним значениям, и поверьте, это проблема. Я использую эту формулу для моей комбинации:

double combo = fact(n)/fact(r)/fact(n-r);

вот psuedocode для моей функции факта:

long fact(int x)
{
int e; // local counter
factor = 1;
for (e = x; e != 0; e--)
{
factor = factor * e;
}
return factor;
}

Какие-нибудь мысли? Я предполагаю, что мои факторные или комбинированные функции превышают максимальные значения или что-то в этом роде.

0

Решение

Вы не упомянули, как это factor объявлен. Я думаю, что вы получаете целочисленные переполнения. Я предлагаю вам использовать двойной. Это связано с тем, что, поскольку вы рассчитываете ожидаемые значения и вероятности, вас не должно сильно беспокоить точность.

Попробуйте изменить функцию факта на.

double fact(double x)
{
int e; // local counter
double factor = 1;
for (e = x; e != 0; e--)
{
factor = factor * e;
}
return factor;
}

РЕДАКТИРОВАТЬ:
Также для расчета nCk вам не нужно вычислять факториалы 3 раза. Вы можете просто рассчитать это значение следующим образом.

if k > n/2, k = n-k.

n(n-1)(n-2)...(n-k+1)
nCk = -----------------------
factorial(k)
1

Другие решения

Вы превышаете максимальное значение лонга. Факториал растет настолько быстро, что вам нужен правильный тип числа — какой тип будет зависеть от того, какие значения вам нужны.

Long — целое число со знаком, и как только вы передадите 2 ^ 31, значение станет отрицательным (используется математика дополнения 2).

Использование unsigned long позволит вам сэкономить немного времени (еще один бит), но для факториала это, вероятно, того не стоит. Если ваш компилятор поддерживает long long, тогда попробуйте «unsigned long long». Это (как правило, зависит от компилятора и процессора) удваивает количество используемых вами битов.

Вы также можете попробовать переключиться на двойное использование. Проблема, с которой вы столкнетесь, заключается в том, что вы будете терять точность при увеличении чисел. Двойное число — это число с плавающей запятой, поэтому у вас будет фиксированное число значащих цифр. Если ваш конечный результат приблизительный, это может сработать, но если вам нужны точные значения, это не сработает.

Если ни одно из этих решений не подойдет вам, возможно, вам придется прибегнуть к использованию математического пакета «бесконечной точности», который вы сможете найти. Вы не сказали, используете ли вы C или C ++; это будет намного приятнее с C ++, так как он предоставит класс, который действует как число и который будет использовать стандартные арифметические операторы.

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector