Если, как всюду советуют в интернете, делать так:
f=((float)rand() / RAND_MAX)*RAND_MAX;
то получаются совсем не случайные числа.
f=((float)rand() / RAND_MAX)*RAND_MAX;
то получаются совсем не случайные числа.
Главная iXBT.com Конференция Блоги Games Видео Market Prosound ПроБизнес РегистрацияВойти | |
brat Member Автор теРСС‹ 39/655 ответов 23 года на iXBT, с января 2002 Чаще пишет Р Р† "Моб. телефоны" (32%) | Если, как всюду советуют в интернете, делать так: f=((float)rand() / RAND_MAX)*RAND_MAX; то получаются совсем не случайные числа. |
nenin Member 2984/32370 ответов 22 года на iXBT, с сентября 2002 Чаще пишет Р Р† "Наука" (51%) | brat: https://www.gnu.org/software/gsl/Если, как всюду советуют в интернете, делать так: f=((float)rand() / RAND_MAX); то получаются совсем не случайные числа. https://www.gnu.org/software/gsl/manual/html_node/Ra…Number-Generation Apropos: делали? |
brat Member Автор теРСС‹ 40/656 ответов 23 года на iXBT, с января 2002 Чаще пишет Р Р† "Моб. телефоны" (32%) | Спасибо. Функция srand(time(NULL)); тут не помогает. Всё равно получаются числа, сидящие на точках, находящихся на равных расстояниях друг от друга (в моём случае - фактически целые числа). Например, такая программа:
выводит результат: 12641.00000 18939.00000 27862.00000 4091.00000 20059.00000 31489.00000 24623.00000 18425.00000 139.00000 9522.00000 Библиотеку GNU сейчас посмотрю. А она стандартная? В MSVC проблем не будет? Добавление от 18.06.2017 10:38: Вообще-то, сейчас я лишь изучаю Си. В книжке в теме про случайные числа я не нашёл аналога паскалевской функции random (которая генерирует качественные случайные вещественные числа от 0 до 1). И возник вопрос: а как это делают сами программисты? У них же есть привычный быстрый и надёжный способ?Исправлено: brat, 18.06.2017 10:58 |
igotm Member 1518/1519 ответов 11 лет на iXBT, с ноября 2013 Чаще пишет Р Р† "Программирование" (99%) | brat эээ... вы чо творите то?... )))... "f=((float)rand() / RAND_MAX)*RAND_MAX;" a - * b = a b хоть в целых хоть в плавающих... удивлены?... это какой класс школы?... третий?... это называетца... барабанная дропь... ДРОБИ!!!... о... согласно приказу от 17.03.1948 года... утверждён устав счетно-караульной службы, раздел 2 пункт 4, читайте со второго абзаца, там поучительная история: А сидела на Б, Б сидела на гаупвахте... К А пришёл другой Б, хотел её размножить... и так далее... и ишо вопрос: а скобки у вас там зачем?... вам бы ещё раз в школу... может быть даже лучче в музыкальную... или в семинарию... Исправлено: igotm, 18.06.2017 14:34 |
brat Member Автор теРСС‹ 41/657 ответов 23 года на iXBT, с января 2002 Чаще пишет Р Р† "Моб. телефоны" (32%) | Я был удивлён лишь тем, что этот способ советуется везде в интернете, хотя с первого же взгляда очевидно что должны получаться числа на равноотстоящих точках, то есть явно не случайные (ведь этих точек максимум 32767). RAND_MAX я выбрал нарочно, чтобы всем было ясно, что этот способ плох. Одна пара скобок, конечно лишняя, но на суть вопроса не влияет. Судя по Вашим словам, Вы - программист (или учитесь на программиста), а значит, отлично знаете язык Си. Не могли бы Вы ответить на мой вопрос? |
ErmIg Member 461/850 ответов 18 лет на iXBT, с января 2007 Чаще пишет Р Р† "Программирование" (49%) Беларусь, Минск Web-страница | Функция rand() возвращает псевдослучайное целое число в диапазоне от 0 до RAND_MAX. Т.е. числа с интервалом в 1. Если результат домножить на любое вещественное число, то можно изменить лишь этот минимальный интервал, но не сам факт его наличия. |
KPAH Expert 3032/18567 ответов 23 года на iXBT, с декабря 2001 232 фото Р Р…Р В° iXBT.photo Чаще пишет Р Р† "Общий" (37%) Россия, Москва | brat Я был удивлён лишь тем, что этот способ советуется везде в интернете, хотя с первого же взгляда очевидно что должны получаться числа на равноотстоящих точках, то есть явно не случайные (ведь этих точек максимум 32767). Это простой совет для простого использования. На самом деле, последовательность этих 32768 чисел может иметь период что-нибудь типа 2(219922−1). Так что может быть возможно брать несколько элементов и набирать псевдослучайное число любой требуемой длины. Но надо быть уверенным, что период не 32768 |
brat Member Автор теРСС‹ 42/658 ответов 23 года на iXBT, с января 2002 Чаще пишет Р Р† "Моб. телефоны" (32%) | KPAH: Спасибо. Так можно (на основе готового кода из интернета, нагугленного после Вашей подсказки)?Так что может быть возможно брать несколько элементов и набирать псевдослучайное число любой требуемой длины. (Вместо RAND_MAX можно вставить требуемую верхнюю границу интервала). Спасибо за поправку насчёт 32768. А вообще я сделал вывод, что в Си общепринятого способа получения вещественных случайных чисел нет. |
KPAH Expert 3033/18572 ответов 23 года на iXBT, с декабря 2001 232 фото Р Р…Р В° iXBT.photo Чаще пишет Р Р† "Общий" (37%) Россия, Москва | brat Так можно? В принципе, подход верный, но есть несколько замечаний: 1) r = r & 0xFFFFFFFFFFFFFFFFULL; писать не требуется. Ну разве что с оглядкой на портабельность - вдруг размер long long будет больше 64 бит. Но тогда и делить на 0xFFFFFFFFFFFFFFFFULL нельзя - вдруг размер long long будет меньше 64 бит. К тому же для портабельности надо будет анализировать RAND_MAX - нет гарантий, что он будет равен 32767, и, более того, нет гарантий, что он будет равен 2N-1 ! 2) c float будет неравномерность - около нуля значения будут расположены чаще. С double тоже - там мантисса всё равно меньше 64 бит. Вот с extended double (который 10 байт и не везде есть) будет равномерность на всём отрезке от 0.0 до 1.0 3) всё-таки попытайтесь узнать, какой именно алгоритм скрывается за rand(). |
kickman Member 7/2061 ответов 17 лет на iXBT, с декабря 2007 Чаще пишет Р Р† "Накопители" (76%) Россия, Родовое Поместье | brat Делайте что-то типа sha1 от текущего момента времени, модифицированного рандомом. Будет рандомнее. Я не пишу на Си, но примерно выглядит так x= sha1 (current_time*rand). Возможно, сделать ещё и с функциями преобразования типов. То есть, получаем длинное целое, а его переписываем побайтово в то место памяти, откуда читаем потом как вещественное. Должно получиться весело. |
alexxela Junior Member 1/2 ответов 7 лет на iXBT, с июня 2017 | в двух словах правильные случайные числа ты не получишь никак, так как все это будет псевдослучайные числа или в вкратце Генератор Псевдослучайных Случайных Чисел (ГПСЧ). Для истинно случайных нужен именно аппаратный Генератор Случайных Чисел. Или если о похожести на случайность это ГПСЧ+источник энтропии. Такой источником каждый придумывает сам в плоть от температуры CPU или связанно с сетевым соединением вариантов можно придумать много. Вывод если что то связано с деньгами ГСПЧ чистый использовать нельзя, его можно взломать. Т.е. на основании предыдущей последовательности получить будущею |
ash of mind Member 1443/4941 ответов, #10 Р Р† рейтинге 17 лет на iXBT, с июля 2007 1 фото Р Р…Р В° iXBT.photo Чаще пишет Р Р† "Программирование" (30%) | alexxela правильные случайные числа ты не получишь никак Правильные случайные числа бывают нужны в 0.01% случаев. И я сомневаюсь, что у человека, который начал изучать язык, тот самый случай. На практике достаточно, чтобы генерируемые последовательности с определенным процентом погрешности удовлетворяли критериям периодичности/предсказуемости. Если не удовлетворяет стандарный rand(), можно взять, например, реализацию mersenne twister. Ссылки на реализации на разных языках (в т.ч. на С) есть здесь. Исправлено: ash of mind, 19.06.2017 05:51 |
Konstantin Mironovich Expert 4907/27210 ответов 25 лет на iXBT, с ноября 1999 Чаще пишет Р Р† "Политика" (35%) | brat Я был удивлён лишь тем, что этот способ советуется везде в интернете, хотя с первого же взгляда очевидно что должны получаться числа на равноотстоящих точках, то есть явно не случайные (ведь этих точек максимум 32767). не знаю кто там чего советует (мало ли в Сети умников), но способ очевидно плохой. традиционный способ - это конвертация целых в интервал [0,1] для конвертации целых в действительные с указанным диапазоном нужно больше информации. первое, что приходит в голову, взять MT19937 для 128bit и делить выхлоп на (MAX128/RAND_MAX). |
nenin Member 2985/32371 ответов 22 года на iXBT, с сентября 2002 Чаще пишет Р Р† "Наука" (51%) | brat: Не знаю. Никогда не пробовал MSVC по известным причинам. А библиотека стандартная. Библиотеку GNU сейчас посмотрю. А она стандартная? В MSVC проблем не будет? Добавление от 19.06.2017 10:22: brat: Те, кому надо быстро и надёжно, используют библиотеки со специальными генераторами под конкретные задачи. В c++11 этот вопрос +/- решён, как дела в голом С, не знаю. И возник вопрос: а как это делают сами программисты? У них же есть привычный быстрый и надёжный способ? |
mockmotor Junior Member 17/26 ответов 7 лет на iXBT, с мая 2017 Канада | brat хотя с первого же взгляда очевидно что должны получаться числа на равноотстоящих точках, то есть явно не случайные Целые числа всё-таки могут быть случайными. Их положение на координатной оси - это вопрос разрешения; тот же компьютерный double тоже представлен битами, и потому также ложится на координатную сетку с определенным шагом -- только несколько более мелким."Всего 32К" - это тоже не критерий неслучайности. Зависит от того, где ты будешь применять генератор. Если у тебя симулируется бросок пары костей, то генератор с диапазоном в 32К представляется вполне достаточным. (Хотя и это не так - нужно смотреть период и прочее). По сермяжному, если ты не можешь предсказать следующее число - то оно (псевдо)случайное. А по научному - есть способы тестирования случайности. Добавление от 19.06.2017 17:42: Konstantin Mironovichтрадиционный способ - это конвертация целых в интервал [0,1] Я думаю, что я понял, что ты хотел сказать. Нужно использовать целочисленные генераторы, главным образом из-за производительности. Следует брать генераторы целых большой размерности (много бит). А конвертация в double потом применяется ввиду того, что большинство применений работает с double. Конвертация сама по себе не улучшает свойств псевдослучайной последовательности, конечно. А то в контексте темы автор может прочитать это как "возьми свой rand(), конвертни в double и будет тебе счастье". Добавление от 19.06.2017 17:45: kickmanx= sha1 (current_time*rand). Почему ты считаешь, что случайность последовательности, полученной таким преобразованием и её период будут лучше, чем оригинальный rand? Gut feeling тут не подходит - тестировать надо.Добавление от 19.06.2017 17:46: igotmBaby... did you forget to take your meds? (C) Placebo Исправлено: mockmotor, 19.06.2017 17:48 |
nenin Member 2986/32372 ответов 22 года на iXBT, с сентября 2002 Чаще пишет Р Р† "Наука" (51%) | mockmotor: brat хотя с первого же взгляда очевидно что должны получаться числа на равноотстоящих точках, то есть явно не случайные Целые числа всё-таки могут быть случайными. |
mockmotor Junior Member 19/28 ответов 7 лет на iXBT, с мая 2017 Канада | nenin Классический генератор, на изотопах, считает количество распадов в определённом временном интервале. Небось дрейфует к нулю за небольшой промежуток в несколько тысяч лет? |
nenin Member 2987/32373 ответов 22 года на iXBT, с сентября 2002 Чаще пишет Р Р† "Наука" (51%) | mockmotor: Народу нравится:nenin Классический генератор, на изотопах, считает количество распадов в определённом временном интервале. Небось дрейфует к нулю за небольшой промежуток в несколько тысяч лет? |
AleX_SPb Member 818/4598 ответов 23 года на iXBT, с октября 2001 Чаще пишет Р Р† "Программирование" (17%) | Интересно, а вариант (double)rand()/(double)(rand()+1) не пойдет? Все равно не идеально, но заметно ближе |
mockmotor Junior Member 20/29 ответов 7 лет на iXBT, с мая 2017 Канада | nenin Народу нравится Чувака реально прёт от этого генератора Dr Holly Krieger на том же канале -- ... с её улыбочкой она мне что угодно могла бы втирать, и я сидел бы с открытым ртом. Добавление от 19.06.2017 20:43: AleX_SPbИнтересно, а вариант (double)rand()/(double)(rand()+1) не пойдет? Пойдет для чего?А если rand(N+1) = линейная f(rand(N))? Тогда и отношение будет постоянным Не, nenin прав - если хочется максимально близкий к случайному генератор, то надо обращаться к природным явлениям. А если не хочется всё усложнять - то нужно проверять генератор на именно тех применениях, где планируешь его использовать. В том видео наверху есть пример, как неидеальный генератор создает артефакты в модели газа. igotm аккаунту вашему 28 дней отроду... Возраст твоего аккаунта, видимо, и объясняет твою маразматическую манеру письма? |
kickman Member 8/2072 ответов 17 лет на iXBT, с декабря 2007 Чаще пишет Р Р† "Накопители" (76%) Россия, Родовое Поместье | mockmotor Почему ты считаешь, что случайность последовательности, полученной таким преобразованием и её период будут лучше, чем оригинальный rand? Gut feeling тут не подходит - тестировать надо. Я и говорил - проверяйте разные способы. Используя время как модификатор, желательно нелинейно. |
mockmotor Junior Member 22/31 ответов 7 лет на iXBT, с мая 2017 Канада | kickman Используя время как модификатор, желательно нелинейно. Время использовать нелинейно - это надо машину времени. |
kickman Member 9/2074 ответов 17 лет на iXBT, с декабря 2007 Чаще пишет Р Р† "Накопители" (76%) Россия, Родовое Поместье | Можно вот так: x= z*random (0..65535)/миллисекунды. |
mockmotor Junior Member 23/32 ответов 7 лет на iXBT, с мая 2017 Канада | kickman x= z*random (0..65535)/миллисекунды. Случайность величины будет зависеть от того, в какие моменты будешь брать текущее время. Если, например, нитка просыпается каждую целую секунду и получает случайное значение, то миллисекунды будут в нижних сотнях - все. Некая неслучайность будет присутствовать. |
vertur Member 4261/4778 ответов, #5 Р Р† рейтинге 16 лет на iXBT, с марта 2008 Чаще пишет Р Р† "Программирование" (52%) Гондурас, default city | brat А вообще я сделал вывод, что в Си общепринятого способа получения вещественных случайных чисел нет. Кроме приведенного выше алгоритма с использованием rand еще нужно переустанавливать ядро генератора при каждом перезапуске в разные значения (функция srand). Делать это надо чтобы получить разные варианты псевдослучайной последовательности при разных запусках. Эти значения ядра генератора лучше всего брать как функцию от текущего времени, айди процесса и айди треда. В редакции POSIX также упомянуты drand48 и erand48 которые генерируют случайный double в диапазоне [0;1) По понятным причинам они не реализованы в Windows версии crt. |
alexxela Junior Member 4/5 ответов 7 лет на iXBT, с июня 2017 | Под windows есть неплохой генератор через WIN API. Присмотритесь к функции CryptGenRandom из wiki заявленные источники энтропии ID текущего процесса. ID текущей нити исполнения. Число тактов с момента последней загрузки. Текущее время. Различные высокоточные счётчики. Хэш-функции MD4 от персональных данных пользователя, таких как логин, имя компьютера, и др. Высокоточные внутрипроцессорные счётчики, такие, как RDTSC, RDMSR, RDPMC. и т.д. |
mockmotor Junior Member 30/39 ответов 7 лет на iXBT, с мая 2017 Канада | igotm само распределение - по Гаусу, если не ошибаюсь в терминах, и годится для большинства применений... А на плоскости? А в трёхмерном пространстве? Один из ранних конфузов с генераторами случайных чисел был как раз с генератором, вполне случайным для одномерных чисел, но размещавщий точки на нескольких плоскостях (не параллельных осям, ЕМНИП), если три последовательных числа брались как (x,y,z). распределение - по Гаусу Исправлено: mockmotor, 21.06.2017 18:39 |
mockmotor Junior Member 32/41 ответов 7 лет на iXBT, с мая 2017 Канада | igotm иа ж написаль - "если не ошибаюсь в терминах" Оказалось - ошибаешься. Надул щёки, накатал простыню - и всё впустую.Генератор СЧ с нормальным распределением - имеет право на существование, но равномерное распределение удобнее - из него можно получить любое другое тривиально. Хотя вот тот генератор на делении радиоактивного вещества - наверняка с нормальным распределением. Ну, nobody's perfect. |