Страницы

Поиск по вопросам

вторник, 28 января 2020 г.

Шансы и варианты

#cpp #алгоритм #случайные_числа


Есть несколько функций, и меняющиеся шансы для их вызова:

void a() { }
void b() { }
void c() { }

float aChance = 0.3f;
float bChance = 0.1f;
float cChance = 0.6f;


Я понимаю, что нужно сгенерировать шанс (0.0f - 1.0f) и сравнить с aChance, bChance
и cChance. Но тогда, если шансы двух переменных одинаковы, вызываться будет та функция,
которая первой стоит в if-else if-else. 

Какой здесь нужен алгоритм? Спасибо!
    


Ответы

Ответ 1



Задача может решаться с помощью стандартного шаблона распределения std::discrete_distribution: std::discrete_distribution<> dist({ список вероятностей }); std::cout << dist(генератор); Пример использования: #include #include #include int main() { std::random_device rd; std::mt19937 gen(rd()); std::discrete_distribution<> dist({ 0.3, 0.1, 0.6 }); std::map m; for (int n = 0; n < 10000; ++n) ++m[dist(gen)]; for (auto p : m) std::cout << p.first << " generated " << p.second << " times\n"; } 0 generated 2980 times 1 generated 1002 times 2 generated 6018 times Ссылка на рабочий пример.

Ответ 2



Как - какой? Сгенерировали? От 0 до 0.3? a() От 0.3 до 0.4? b() От 0.4 до 1? c() Больше 1? Фигню сгенерировали :) double p = rand()/double(RAND_MAX+1); if (p < aChance) a(); else if (p < aChance+bChance) b(); else if (p < aChance+bChance+cChance) c(); else error("Так не бывает");

Ответ 3



http://ideone.com/kOvj7F Обращаю внимание, что последний элемент массива 1, а не сумма. Это нужно, чтобы избежать погрешности при сложении. А ещё можно всё поумножать, чтобы работать с целыми. #include #include int aCount = 0, bCount = 0, cCount = 0; void a() { ++aCount; } void b() { ++bCount; } void c() { ++cCount; } float aChance = 0.3f; float bChance = 0.1f; float cChance = 0.6f; const size_t n = 3; float chance[n] = {aChance, aChance + bChance, 1}; void (*f[n])() = {a, b, c}; int main() { for (unsigned t=0; t<1000000; ++t) { float x = rand() / (float)RAND_MAX; for (unsigned q=0; q

Комментариев нет:

Отправить комментарий