[C]смоделировать вероятность
я имею в виду функцию, которая с вероятностью p выдаёт 1, а с вероятностью (1-p) выдаёт 0
Делить на RAND_MAX нельзя, у тебя получится неравномерное распределение. Для того, чтобы смоделировать маленькую вероятность, надо просто вызывать rand несколько раз. Типа два события с вероятностью 0.1 вместе выполняются с вероятностью 0.01
ну да, я эти общие идеи понимаю, просто торможу, как свести к вероятности p
Тебе нужна вообще произвольная вероятность?
ага, ну т.е. она хранится в double p, подаю эту переменную функции, и эта функция с вероятностью p говорит ok
Самый простой способ - написать функцию long_rand:
При необходимости взять большее число вызовов rand до достижения желаемой точности.
После этого, ты сможешь делать:
long long_rand
{
return long)rand * RAND_MAX + (long) rand;
}
При необходимости взять большее число вызовов rand до достижения желаемой точности.
После этого, ты сможешь делать:
int isOk(double p)
{
return double)long_rand / long) RAND_MAX) * long)RAND_MAX < p;
}
что-то типа того:
bool RandBool(double prob) {
// RAND_MAX = 100; // говорят в С нельзя менять.
if (prob > 0) {
do {
prob *= RAND_MAX;
if (prob >= 1)
return rand < int(prob + 0.5);
} while (rand == 0);
}
return false;
}
rand == 0 ровно в 1/32768 случаев, совсем не ясна твоя идея.
Разве в твоём примере будет равномерное распределение вероятности?
rand == 0 ровно в 1/32768 случаев, совсем не ясна твоя идея."Типа два события с вероятностью 0.1 вместе выполняются с вероятностью 0.01"

rand == 0 ровно в 1/RAND_MAX случаев, или я путаю?
RAND_MAX не меняется в Си.
ну тогда закомментить первую строчку в функции
может в коде я где-нть и ошибся, но идея в целом выражена
может в коде я где-нть и ошибся, но идея в целом выражена
double next_prob = prob * RAND_MAX;
if (next_prob >= RAND_MAX)
return rand < prob;
Это условие выполняется только при prob равном единице.
поправил, теперь вроде должно работать
Будет, но надо к RAND_MAX добавить 1.
Разве в твоём примере будет равномерное распределение вероятности?

prob *= RAND_MAX;
if (prob >= 1)
return rand < prob;
Даже если поправить на RAND_MAX+1, то у тебя при p равном 0.001 условие будет выполняться с вероятностью ~0.000977
вот прикопался!
это уже тонкости, добавь +1 в нужных местах.
я тут стратегией занимаюсь
это уже тонкости, добавь +1 в нужных местах.
я тут стратегией занимаюсь

Ну заметь, что у Красина стратегическая точность всё-таки повыше. 

всем спасибо 

у Красина стратегическая точность всё-таки повыше."стратегическая точность" - это как? Эти слова как рядом оказались?
Мой способ - это просто аналитическое расширение его способа. В том смысле, что его способ - есть случай второй итерации моей функции. Причем его способ с делением, а мой - нет.
Слова рядом оказались, потому что ты написал про стратегию.
"стратегическая точность" - это как? Эти слова как рядом оказались?
Мой способ - это просто аналитическое расширение его способа. В том смысле, что его способ - есть случай второй итерации моей функции. Причем его способ с делением, а мой - нет.
Твой способ отличается с точки зрения точности решения: до 10% погрешности. Да, твой способ без деления, только у тебя rand вызывается два раза на n-1 итерациях, а там тоже есть деления.Слова рядом оказались, потому что ты написал про стратегию.Стратегия - это web page
только у тебя rand вызывается два раза на n-1 итерациях.не угадал.
Не угадал чего? Что два раза вызывается - так и есть. А что в rand есть деления... Может и нет, но я не думаю, что ряд сдвигов и перестановка элементов массива в памяти гораздо лучше одного деления. Давай продолжим спор, когда ты напишешь код так, что погрешность твоего метода будет меньше 1%.
не угадал, что 2 раза вызывается
а ка ты мерял распределение?
или аналитикой вывел?
а ка ты мерял распределение?
или аналитикой вывел?
Сколько же по-твоему раз вызовется rand в твоём коде, если при первой итерации p будет меньше 1.0?
А распределение я никак не мерял, у тебя погрешность в вероятности. Как я сказал, для p = 0.0001 вероятность возврата true будет 0,000092.
А распределение я никак не мерял, у тебя погрешность в вероятности. Как я сказал, для p = 0.0001 вероятность возврата true будет 0,000092.
Сколько же по-твоему раз вызовется rand в твоём коде, если при первой итерации p будет меньше 1.0?один!
ты меня так смутил, что я даже проверил!
Ну вот, вызывается 1 раз и потом ещё 1 раз. Я просто ошибся в том, что написал. Ладно, с этой стороны всё ок. Вернёмся к погрешности...
может ты тогда поделишься своими выкладками, а то у меня все нормально получается...
кажись, я понял, что ты имеешь в виду...
щас подумаем...
щас подумаем...
хотя нет, не понял 

Ну я могу ошибаться. Давай подумаем, ты всегда отсекаешь десятичную часть при сравнении rand < p.
Это значит, что при 3.2767 срабатывание будет на числах 0, 1, 2, 3. Эти числа выкидываются с вероятностью ~0,000122; и т.п.
Это значит, что при 3.2767 срабатывание будет на числах 0, 1, 2, 3. Эти числа выкидываются с вероятностью ~0,000122; и т.п.
я сначала подумал об этом, но потом понял, что при округлении или добавлении 0.5 при сравнении оно на самом деле усреднится к 0.
так что правлю код на +0.5...
еще замечания будут?
а сбило меня с толку, что неявное приведение в паскале работает как округление в отличие от С
так что правлю код на +0.5...
еще замечания будут?

а сбило меня с толку, что неявное приведение в паскале работает как округление в отличие от С

Я ошибся в выкладках. А предложенное тобою решение только ухудшило ситуацию. Впрочем, отрезая десятичную часть ты никогда не добьёшься стабильно малой погрешности.
1) вроде ничего не ухудшил
2) я тебя огорчу, но на RAND_MAX=32768 далеко не уедешь... Дискретность останется всегда... В моем примере дискретность остается в точности такая же, как и в rand для p=O(0.1) и скачками уменьшается при p-> 0.
Альтернатива - это написание полностью своего генератора с меньшей дискретностью, чем rand.
Но это совсем другая история, хотя тоже вполне реальная...
2) я тебя огорчу, но на RAND_MAX=32768 далеко не уедешь... Дискретность останется всегда... В моем примере дискретность остается в точности такая же, как и в rand для p=O(0.1) и скачками уменьшается при p-> 0.
Альтернатива - это написание полностью своего генератора с меньшей дискретностью, чем rand.
Но это совсем другая история, хотя тоже вполне реальная...
1. p = 0.0001, p*MAX=3.2767, rand < 3 в ~0,000092, всё ещё больше 1%
2. Я не требовал убрать дискретность, я просто сравнивал с тем, что у Красина. Для приведённых в первом топике чисел у него погрешность меньше 1%.
2. Я не требовал убрать дискретность, я просто сравнивал с тем, что у Красина. Для приведённых в первом топике чисел у него погрешность меньше 1%.
я просто сравнивал с тем, что у Красина. Для приведённых в первом топике чисел у него погрешность меньше 1%.согласен, это потому что у него всегда юзается 2 rand а уменя не всегда, а только при необходимости "углубления" к нулю. Мою процедуру можно легко заставить делать 2 итерации (чтобы юзалось 2 вызова ранд-а) и тогда точности сравняются.
Ну свяжи и посмотри, что получается. А потом скажи, чем это лучше того, что у Красина? 

лучше тем, что оно может работать и для 1е-10 и для 1е-200 

Ну свяжи и посмотри, что получаетсявсе очень просто:
bool RandBool(double prob) {
// RAND_MAX = 100; // говорят в С нельзя менять.
if (prob > 0) {
do {
prob *= RAND_MAX * RAND_MAX;
if (prob >= 1)
return rand*RAND_MAX+rand < int(prob + 0.5);
} while (rand == 0 && rand == 0);
}
return false;
}

Лучше б рекурсию написали -- сложнее ошибиться.
bool f(double p) {
if (p > 0.1) {
return rand < RAND_MAX * p;
} else {
return f(0.2) && f(p*5);
}
}
Если не критично время, то можно по ЦПТ (много раз сгенерить случайное число и нормировать - получим нормальное распределение).
Только нужно знать квантиль нормального распределения.
Только нужно знать квантиль нормального распределения.
Оставить комментарий
stm7868162
Как с помощью rand смоделировать, например, вероятность p=0.007, или p=0.0000000001 (во втором случае меньше, чем 1/RAND_MAX)?А то что-то я туплю