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

0

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

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

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

Затем предполагается, что программа выведет ожидаемые значения получения x количества голов. Например, если монета была перевернута 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 и отрицательные значения для значения, которое должно быть xxx.

Отладка, я заметил, что 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
    Возможно, вы получаете целочисленные переполнения. Попробуйте изменить типы на удвоение для функции факта и посмотрите, принимаются ли более высокие значения.
  • 0
    Здесь: stackoverflow.com/a/4701106/576911 - это способ вычисления nCk с минимальной опасностью переполнения, и, если переполнение действительно происходит, оно не делает это молча.
Теги:
combinations
probability
factorial

2 ответа

1
Лучший ответ

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

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

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

EDIT: Также для вычисления nCk вам не нужно вычислять факториалы 3 раза. Вы можете просто вычислить это значение следующим образом.

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

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

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

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

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

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню