Задача Монти Холла C Моделирование Монте-Карло

Поэтому, увидев еще одно видео о задаче Монти Холла и узнав о методах моделирования Монте-Карло, я подумал, что попытаюсь найти процент 66,66% победы в игре, если вы поменяете двери. Проблема в том, что я получаю 50%, и при обдумывании алгоритма меня беспокоило одно: верна ли моя модель. У меня было реализовано 2 случайных предположения: одно для выбора дверей с 1 по 3 с шансом 1 из 3 и одно для выбора переключения дверей с шансом 1 из 2. Утверждения if предназначались для назначения дверей с призами и для различных возможностей для каждого из этих предположений. Я не знаю, смогу ли я уменьшить эту часть, но пока это работает (я думаю). Где мое мышление было неверным? И можете ли вы предложить исправить мой алгоритм? Большое спасибо!

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
int main()
{
    int seed=time(NULL);
    srand(seed);
    double u, random[2], suitch=0.0, total=0.0;
    int nall=10000000, nright=0, i, door[3], k, j;
    for(j=0; j<nall; j++)
    {
        for(i=0; i<3; i++)
            random[i]=0.0, door[i]=0;
        for(i=0; i<2; i++)
        {
          u=(1.*rand())/RAND_MAX;
            random[i]=3.*u;
            //printf("%lf\t%lf\n",u,random[i]);
        }
        suitch=2.*u;
        //printf("%lf\n",suitch);
        if(floor(random[0])==0)
            door[0]=1, door[1]=0, door[2]=0;
        else if(floor(random[0])==1)
            door[0]=0, door[1]=1, door[2]=0;
        else if(floor(random[0])==2)
            door[0]=0, door[1]=0, door[2]=1;
        for(i=0; i<3; i++)
            //printf("%d\t",door[i]);
        if((floor(random[1])==0)&&(floor(suitch)==0))
            k=door[0];
        else if((floor(random[1])==1)&&(floor(suitch)==0))
            k=door[1];
        else if((floor(random[1])==2)&&(floor(suitch)==0))
            k=door[2];
        else if((floor(random[1])==0)&&(floor(suitch)==1))
            {
                if(door[1]==1)
                k=door[1];
            else if(door[1]==0)
                k=door[2];
            }
        else if((floor(random[1])==1)&&(floor(suitch)==1))
            {
                if(door[0]==1)
                    k=door[0];
                else if(door[0]==0)
                    k=door[2];
            }
        else if((floor(random[1])==2)&&(floor(suitch)==1))
            {
                if(door[0]==1)
                    k=door[0];
                else if(door[0]==0)
                    k=door[1];
            }
        if(k==1)
            nright++;
    }
    total=1.*nright/nall;
    printf("%d\t%d\t%lf\t", k, nright, total);
    return 0;   
}

person Negafilms Origins    schedule 22.03.2020    source источник
comment
На первый взгляд, я думаю, вы не рассматривали возможность использования имен переменных и функций, чтобы вы могли сказать, что происходит? Возможно, опишите основную проблему в комментарии, если вы действительно хотите переборщить.   -  person Kenny Ostrom    schedule 22.03.2020
comment
Доступ к random осуществляется вне диапазона.   -  person Kenny Ostrom    schedule 22.03.2020
comment
Я предполагаю, что random[2] представляет, где находится приз. Вы неправильно моделируете положение приза как движущееся. Он никогда не двигается. (Я спрашиваю, представляет ли это случайный выбор здесь, прежде чем опубликовать ответ, хотя - требует пояснений.)   -  person Kenny Ostrom    schedule 22.03.2020
comment
Мои познания в программировании очень базовые и достаточно простые, чтобы решать физические и математические задачи. Я не знаю всего, что может сделать язык c. Просто на заметку, чтобы люди не говорили, почему вы не сделали это так, использовали то, добавили то и т. д. Я просто хочу разобраться в логике алгоритма.   -  person Negafilms Origins    schedule 22.03.2020
comment
Random[2] выбирает, хотите ли вы переключаться или нет (floor(random[2])=0-›без переключения, floor(random[2])=1-›switch). Door[3] — призы (1=выигрыш, 0=проигрыш).   -  person Negafilms Origins    schedule 22.03.2020
comment
Открытие не той двери осуществляется с помощью последних 3 операторов if. Во-первых, выбирается дверь и решается выбор для переключения, затем она выглядит одной из закрытых дверей, если это приз, неправильная дверь отбрасывается, когда она выигрывает, если вы переключаетесь. Если у него нет приза, он выбирает оставшуюся дверь.   -  person Negafilms Origins    schedule 22.03.2020
comment
Вероятность suitch использует то же случайное число, что и random[1], что делает два числа связанными, что делает симуляцию недействительной.   -  person 1201ProgramAlarm    schedule 22.03.2020
comment
Было бы проще, если бы вы генерировали случайные числа, такие как stackoverflow.com/questions/5008804/   -  person Kenny Ostrom    schedule 22.03.2020
comment
(1.*rand())/(RAND_MAX) неправильно. Иногда rand() возвращает RAND_MAX, поэтому он выдает 1, когда требуются только значения строго меньше 1.   -  person Eric Postpischil    schedule 22.03.2020
comment
suitch=2.*u; неправильно. u не менялся с тех пор, как он использовался для установки random[1], поэтому suitch не является независимым от random[1]. Это устанавливает suitch в 0 из random[1] равно 0, в 0 или 1 примерно в половине случаев, когда random[1] равно 1, и в 1 почти каждый раз (из-за проблемы RAND_MAX выше) random[1] равно 2. Однако это может не повлиять на среднюю вероятность, поскольку случаи симметричны между значениями random[1].   -  person Eric Postpischil    schedule 22.03.2020
comment
Я знаю, что мои переменные не являются независимыми и одна влияет на другую, но это экономит место и время, пытаясь написать другой способ получения случайных чисел. Я мог бы написать функцию и вызывать ее каждый раз, когда мне нужно произвести случайное число, но именно так я думал сделать это во время написания кода. И вы правы, говоря, что случайное число, такое как 1, может вызвать проблемы для алгоритма, но, на мой взгляд, шансы очень малы, и это не влияет на 10 ^ 8 повторений. Кроме того, это было чем-то для меня, чтобы повеселиться, так что меня это пока не волнует.   -  person Negafilms Origins    schedule 22.03.2020


Ответы (1)


Я слишком долго смотрел на ваш код, не в состоянии увидеть проблему. Каким же я был идиотом, лол. С кодом никаких проблем (за исключением случайного и, к счастью, безопасного переполнения памяти). Проблема в том, что вы пытаетесь смоделировать.

Вы моделируете 1 000 000 игр, где в половине случаев игрок решает оставить свою дверь (его шанс 33,3 % в этом случае) и в половине случаев игрок решает переключиться (его шанс 66,7 % в этом случае). Конечно, вы получаете 50%, потому что именно это вы имитируете.

Установите suitch = 1 навсегда, и вы... получите 66,7%

И да... пожалуйста, сделайте случайные 3 элемента длинными или остановите инициализацию в начале, чтобы исправить переполнение памяти, и закомментируйте прежний отладочный for(i=0; i<3; i++), потому что вы запускаете цепочку ifs моделирования 3 раза на каждой итерации без уважительной причины. Но это не связано :-)

person Boris Lipschitz    schedule 22.03.2020
comment
Во-первых, я извиняюсь за то, что мой код слишком ужасен и сложен для понимания того, что делает кто-либо, кроме меня. Когда я ложился спать прошлой ночью, я думал о том, как лучше понять проблему Монти Холла, придумав все возможные сценарии, которые могут произойти в игре. Потом я разобрался с проблемой логики кода. Мой код считается выигрышным в обеих стратегиях, с переключением и без переключения. Таким образом, фактический результат будет составлять 50% процента выигрыша, если вам все равно, какую стратегию вы используете. Когда я удалил часть без переключателя или использовал костюм = 1, я получил 66,6%. Кстати, переполнения памяти нет. - person Negafilms Origins; 22.03.2020
comment
@NegafilmsOrigins: Очень простой способ понять проблему Монти Холла: представьте себе 3000 столов с 1 красной картой и 2 черными картами лицом вниз. 3000 ваших клонов случайно указали пальцем на карту. Случайно, примерно за 1000 столов, ваши клоны оказались на красных карточках. За каждым столом покажите карту, на которой нет пальца и которая не красная. За сколькими столами ваши клоны держат красные карточки? Еще 1000, потому что они и пальцем не пошевелили. Следовательно, оставшись с первым выбором, вероятность выигрыша составляет 1/3. Таким образом, переключение должно иметь вероятность 2/3. - person Eric Postpischil; 22.03.2020
comment
Я думаю об этом так: если 1 — это выигрыш, 0 — проигрыш, а 100 — выигрыш двери 1 и проигрыш двери 2 и 3, то у нас есть 3 версии: 100, 010, 001. Если вы каждый раз выбираете одну конкретную дверь, например дверь 1, у вас есть 1/3 шансов на победу без переключения. Но если вы переключитесь, у вас есть 2/3 шансов выбрать не ту дверь, и если ведущий откроет другую неправильную дверь, вы автоматически выиграете. - person Negafilms Origins; 22.03.2020
comment
Поверь Борис, я смоделировал игру 1000000000 раз и выиграл 666 миллионов автомобилей. И теперь я трачу деньги, ища место, чтобы припарковать их всех. - person Luis Colorado; 27.03.2020
comment
@LuisColorado в качестве бонуса, теперь у вас должно быть достаточно коз, чтобы накормить всю планету. Или... перегреть его козьим пердежом. - person Boris Lipschitz; 27.03.2020