На днях возник такой вопрос: как реализуется функция rand() в с++? попутно и srand().
я знаю, как примерно выглядят эти функции, но хотел бы точно увидеть код или узнать библиотеку, в которой они лежат (облазив весь cstdlib, stdlib.h их реализации не нашел)
нашел такой вариант реализации
но 1) верен ли он? 2) что такое 1103515245m? точнее, что такое m?
Верность проверяем просто вычисляя рандом этим алгоритмом и родным: ответ — нет (как минимум на моем гну) Префикс m не компилируется (опять же на моем гну), как и отсутствие плюса (или что там должно быть??) перед 2768 :)
Где-то может и так. А вообще — по разному.
тут есть код, только там без m http://goo.gl/nPbEJ
Например, так: stdlib/random_r.c в GNU C Library. А в стандарте POSIX можно найти более простой пример, который предлагается к использованию.
не пойму, где там реализация rand()
В glibc
rand()
вызывает функцию__random()
, которая вызывает функцию__random_r()
, которая определена в этом файле.Скорее,
Nevermind.
Стандарт вроде бы ничего не говорит про реализацию, предъявлены только некоторые формальные требования, так что вопрос не совсем корректен, надо спрашивать "как реализован rand() в моем компиляторе".
А если в общем, то на этот вопрос все-таки можно ответить — rand() в c++ реализован плохо. Практически везде, насколько мне известно.
А чем он плох?
Ну, начиная хотя бы с того, что числа получаются не случайные. =) Это не шутка, сгенерировать достаточно "равномерную" и "независимую" псевдослучайную выборку очень сложно. На википедии хорошо про это написано.
Мне даже кто-то рассказываел баечку про то, что в каком-то из компиляторов (возможно, не сишном) ГСЧ никогда не выкидывал ноль, в принципе.
По сути вопроса конкретных тестов привести не готов, просто из собственного опыта говорю. Предлагаю поверить на слово или проверить самому. =)
Хороший генератор случайных чисел это такой что мы не можем предсказать по некоторой последовательности сгенерированных псевдослучайных чисел, что будет за следующее число. Тут такого свойства не наблюдается :)
UPD Придумался пример. Пусть у нас seed просто увеличивается на 1, а генератор возвращает sha-хэш (или его часть) от seed. Тогда в общем случае мы не можем по последовательности хэшей сказать, что будет дальше.
Точнее это свойство ГСЧ называется криптостойкостью.
Что значит "плохо"? Это смотря какие требования мы выдвигаем. Понятно что для некоторых вероятностных алгоритмов нужны случайные числа, и в зависимости от задачи иногда лучше использовать сторонние крутые библиотеки, нежели встроенную функцию, но для ацм вполне хватает
rand()
Да, для этого хватает, конечно.
Хотя вот у некоторых компиляторов rand() не выкидывает числа больше 2^15 — 1. Неприятно во время какого-нибудь контеста это обнаружить, наверное.
Я всегда считал, что числа до 15 бит на MS и 31 или 32 на линуксах, поэтому проблемы здесь не вижу. Нужно аккуратно использовать, иногда надо сгенерить число 64-битное, проблемы нет в том чтобы подвигать да поксорить.
cerr << RAND_MAX << endl;
Так сейчас в c++0x есть нормальные рандомы куча распределений) и они по моему более менее адекватно работают...
http://www.velocityreviews.com/forums/t435632-rand-implementation.html
Совпадает :) Код любезно взят из visual studio. При отладке нужно просто зайти вглубь rand и там почти тоже самое написано. Так как стандартом rand походу не закреплен — на linux может и не совпасть. Кто проверит — отпишитесь ниже пожалста :)
Полный код для лентяев
магия) где вы это нашли?
Ну например в моем комментарии выше, первый результат гугла по запросу rand implementation
спасибо
На gcc 4.4.3 не совпадает и даже не похоже — выдаёт какие-то подозрительно маленькие числа.
UPD: "подозрительно маленькие" — видимо, вот причина
Windows? У меня gnu 4.5.2 и visual studio 2010 на windows согласны. Тут вопрос в том пользуется ли твой компилятор услугами msvcrt.dll и какой версии.
Нет, Linux Ubuntu 10.04, забыл самое главное указать :)
А, ну тогда вопросов нет :)
**_кроме одного, давно хотел спросить, прощу прощения, но.. тебя серьезно так звать?_**
Да =)
Линейный конгруэнтный метод Более качественные генераторы есть в Boost: http://www.boost.org/doc/libs/1_49_0/doc/html/boost_random/reference.html#boost_random.reference.generators