1. C++ / Говнокод #15582

    +15

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    int getRandomNumber(){
       int Number[1];
       return Number[6];
    }
    //Я только учусь, поэтому не судите строго.

    И кому теперь нужно srand(GetTickCount());

    Запостил: Ignat776, 26 Марта 2014

    Комментарии (58) RSS

    • http://en.wikipedia.org/wiki/Address_space_layout_randomization
      return (int) &system;
      Ответить
    • > И кому теперь нужно srand(GetTickCount());
      В с++ то? Никому. Юзай вменяемые boost::random (везде) и std::random (в с++11), а не дикое сочетание тормозного, неудобного и устаревшего говна srand() с виндоблядской апишкой GetTickCount().
      Ответить
      • rand не достаточно рандомен?
        Ответить
        • > rand не достаточно рандомен?
          Во-первых - да. У него очень маленький seed и достаточно хреновое распределение. Впрочем как и у любого другого линейного конгруэнтного генератора.

          Во-вторых он лагает как говно, если его юзать из нескольких тредов (производительность проседает где-то в 100(!) раз по сравнению с одним тредом). Ибо состояние глобальное.

          В-третьих он тупо неудобен, т.к. нужное распределение из его выхлопа надо получать самому.
          Ответить
          • То есть если нужно сгенерить пароль... Или ключ шифрования? Эмм... Это же в продакшен уходило...
            Ответить
            • > То есть если нужно сгенерить пароль... Или ключ шифрования?
              То нужно юзать криптостойкий ГПСЧ, который прилагается ко всем приличным криптобиблиотекам. Этому требованию не удовлетворяет ни один генератор из boost::random/std::random (ну кроме random_device, но у него свои заморочки), что уж говорить о rand().

              С 32 битным сидом rand()'а достаточно перебрать всего 4 миллиарда вариантов, и ты получишь все пароли и все ключи, которые могла сгенерить система ;) А если его еще и сдуру проинициализировали временем... Да еще и делали это на каждом запросе... Брр... Не дай бог приснится такое, носками не отмашешься.
              Ответить
              • > std::random
                А что там за заморочки?
                Ответить
                • random_device то? Ну он не на всех платформах работает. А остальные ГПСЧ тупо не криптостойкие.
                  Ответить
                  • он прямо из /dev/random берет данные?
                    Ответить
                    • Использует криптографически секурный источник если возможно. Т.е. /dev/random, Виндовский аналог, либо встроены в процессор генератор. Либо ещё какие костыли решения для целевой платформы.
                      Ответить
                      • >либо встроены в процессор генератор
                        ...,протрояненный анб
                        Ответить
                        • не анб, так китайсами, не ими, тогда фсб.
                          задолго до "откровений" Сноудена я читал, что все устройства и алгоритмы были ОБЯЗАНЫ содержать бэкдор или ослабленный алгоритм для доступа силовых структур "на случай чего", иначе бы они не прошли одобрямс (сертификация, патент, разрешение - или как это грамотно называется)
                          в свое время был скандал с PGP, мол, этот алгоритм слишком секюрный, и его существенно ослабили перед доведением до общественности.

                          просто тогда никто не придавал этому никакого значения
                          а я и сейчас не придаю, на фоне общей истерии, потому как уже поздно что-либо скрывать, все уже утекло и в фсб и в фбр, и гуглам всяким
                          Ответить
                          • Это мохнатые годы. После историй с pgp, когда исходники распечатывались, пересылались через границу и там сканировались, чтобы обойти запрет на экспорт, америка сдалась. Кстати, а поддержку модуля не больше килобита в жавке в biginteger без доустановки какой-то хуйни уже запилили?
                            Ответить
                        • > ...,протрояненный анб
                          Эт еще хуйня. Про intel management engine читал? Большой брат уже в твоем чипсете ;)
                          Ответить
                          • еще есть опасения, что UEFI может выступать в роли хоста для виртуальных машин. КСЖ
                            Ответить
                            • Параноики могут вынести UEFI, заменив его на coreboot какой-нибудь. А вот от Intel ME так просто не избавишься. Этот второй проц все равно будет что-то делать, у него ведь не вся прошивка на флешке с биосом, часть намертво вшита в него.

                              > хоста для виртуальных машин
                              Вполне достаточно SMM, который и bios и uefi вроде как всегда юзают (якобы для управления энергосбережением и прочей ерундой, но мы то знаем...).
                              Ответить
                              • P.S. Повысим градус паранойи: ME вроде бы как раз может загонять основной проц в SMM чтобы поговорить с ним наедине... И у ME есть доступ к сетевухе (wake-on-lan вроде бы как раз через него запилен)...
                                Ответить
                                • Можно зашить свой биос, можно поковыряться в своем. Я подозреваю многие биосы на этот вопрос уже исследованы низкоуровневыми параноиками и если были бы проблемы - они бы уже кричали. А вот встроенный в проц механизм контроля за тротлингом, температурой и прочей фигней - вполне себе софтварный и может содержать фсбешную прошивку от большого брата.
                                  Ответить
                                  • > Можно зашить свой биос
                                    А я о чем выше?

                                    Биосы то можно исследовать. А вот ME, насколько показали поиски в гугле, является конфиденициальной инфой, и его так никто и не смог разломать и даже разобрать его прошивку (впрочем это хорошо, не хватало еще вирусов на этом сопроцессоре).
                                    Ответить
                          • Ох ёб вашу мать. Это http://ru.wikipedia.org/wiki/Active_Management_Technology ? Это как-то отключается?
                            Ответить
                      • > /dev/random
                        /dev/urandom по дефолту. Но можно поменять.
                        Ответить
            • Можно использовать правило 30, или правило 110 (или даже лучше - правило 45 - вроде как меньше всего коллизий), единственное что - нужно как-то творчески подойти к первоначальному состоянию.
              Ответить
          • > он лагает как говно, если его юзать из нескольких тредов
            Wat?
            rand в студии использует tls
            Ответить
            • И у каждого треда свой seed? Круто, чо... Майкрософт как всегда в своем стиле.

              Очень весело будет, если кто-то проинициализирует seed в main'е, и наивно будет думать, что и в других тредах тоже все будет норм. А на деле они тупо начнут с единички...

              Кстати, об этом написано в документации? Можно пруф?
              Ответить
              • > Кстати, об этом написано в документации? Можно пруф?
                Не знаю что там в пруфах, но у меня в прерываниях rand не работал. Падало при попытке чтения tls. Если не ошибусь то как раз при чтении FS:[0].
                Ответить
                • > прерываниях
                  Блин, а в виндовых драйверах разве можно юзать rand()?
                  Ответить
                  • А почему бы и нет?

                    Не, не виндовый. Есть некие наркомы, что заюзали для своей оси кресты со студией. Не будем о грустном.
                    Ответить
                    • Кстати так и дошли до того что написали mysrand и тд, который копипаст кода с CRT, но только с глобальным состоянием.
                      Ответить
            • В общем ты только что забил еще один гвоздь в крышку гроба srand() - полная несовместимость между платформами.

              P.S. Насчет скорости - тестил на gcc под линухом. Там сид не в TLS, поэтому лагает как говно.
              Ответить
              • srand
                Зато название говорящее.
                По имени функции должно быть ясно что внутри, а именно - срандь.
                Ответить
          • >производительность проседает где-то в 100(!) раз

            это ты выяснил когда мой говнокод проверял?
            Ответить
          • а на {d,l}rand48() нагнать чего можешь? я ими пару раз пользовался.
            Ответить
            • > а на {d,l}rand48() нагнать чего можешь? я ими пару раз пользовался.
              1) Посикс-онли.
              2) Тож самое линейно-конгруэнтное говно, что и rand(). Просто бит побольше.
              3) Надпись в мане гласит: These functions are declared obsolete by SVID 3, which states that rand(3) should be used instead.
              Ответить
              • очень странно.

                SVID 3 == "Version 3, based on System V Release 4, published 1989"

                в посиксе о обсолишн ничего не написано:
                http://pubs.opengroup.org/onlinepubs/9699919799/functions/drand48.html

                в манах ванила SVR4 (ака солярка) тоже ничего такого не говорится:

                http://www.freebsd.org/cgi/man.cgi?query=drand48&apropos=0&sektion= 0&manpath=SunOS+5.10&arch=default&format =html
                Ответить
        • http://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful
          Ответить
          • Злая шутка про то, что одноглазым его сделал rand()
            Ответить
            • Еще одна злая шутка: Кресты позволяют прострелить себе не только ногу, но и глаз.
              Ответить
          • Say you have a problem, so you use floating-point.
            Now you have 2.000001 problems.
            Ответить
          • Он там писал:
            int src = rand();
            int dst = static_cast<int>(src*1.0/MAX_RAND)*99;//Беда! Не нормальное!

            А что если написать как ниже для получения нормального распределения [0..99]? Видите проблемы кроме говнокода?
            int src = rand();
            double d = (src*1.0/MAX_RAND)*100.0;
            double t = d<0.5 ? 100.0 : ceil(d-0.5);
            int dst = static_cast<int>(t)-1;
            Ответить
            • > нормального распределения
              Равномерного. Нормальное совсем не так выглядит.

              > Видите проблемы
              Вижу. Распределение не равномерное ;)

              Пруф для сомневающихся: http://ideone.com/GnSkao

              P.S. Да еще и плавучка юзается, походу этот код будет работать медленнее uniform_distribution.
              Ответить
              • С вашей проверкой код Stephan T. Lavavej тогда вообще не работает? о_О
                http://ideone.com/wz0bcx
                Если что код на 6:49

                PS: Насчет перевода uniform - описка.
                Ответить
                • > код Stephan T. Lavavej тогда вообще не работает?
                  Кто-то доигрался с экономией скобок ;)

                  http://ideone.com/NikpHq
                  Ответить
              • Эмм, проверка на равномерность может быть осуществлена только для population, то есть бесконечного множества чисел (что не осуществимо). На sample (т.е. выборки в 32к чисел например) нужно применять разные статистические методы, например chi-square test

                Так что распределение по ссылке - равномерное (считать лень).
                Ответить
                • А проверять так - можно. Мы полагаем, что исходное распределение равномерно. Т.е. все 32768 чисел равновероятны. Преобразование, используемое в коде по ссылке портит вероятности - часть чисел на выхлопе вероятнее, чем остальные. Поэтому распределение не равномерное.

                  > Так что распределение по ссылке - равномерное
                  Ну тогда надо писать критерий и доверительный интервал :)
                  Ответить
                  • > Ну тогда надо писать критерий и доверительный интервал :)
                    Дык тест chi-square это и позволяет делать

                    > Преобразование, используемое в коде по ссылке портит вероятности - часть чисел на выхлопе вероятнее, чем остальные.
                    Не совсем. Часть чисел выпали чаще чем остальные, но это также может объясняться и недостаточностью выборки. Если вам выпало 10 раз подряд 6-6 это же не делает вас супервезучим игроком в Нарды, ведь так ;)
                    Ответить
                    • Ну тут они не просто криво выпали, а систематически выпадают чаще. Это как немного несимметричная кость, у которой вероятность выпадения 6 чуть-чуть больше остального.

                      Было 32768 равновероятных исходов. 32700 из них равномерно размазали по сотне выходов. Но остались 68 лишних. И они ВСЕГДА будут падать в одни и те же выходы (т.к. алгоритм такой). Это именно систематическая ошибка, а не случайная.
                      Ответить
            • Оно всё ещё не равномерное: некоторые числа будут встречаться чаще других. Ну невозможно равномерно отобразить множество целых чисел X на множество Y если |X| % |Y| != 0.
              Ответить
              • > невозможно равномерно отобразить множество целых чисел X на множество Y если |X| % |Y| != 0.
                Возможно. И даже реализовано в бустовском распределении ;)

                Один из способов (который там и юзается) - тупо отбрасывать числа >= floor(|X| / |Y|) * |Y| и брать следующее случайное число. Тогда распределение на выходе будет равномерным.
                Ответить
                • Вот кстати первое что подумал, а потом решил не делать, а то вдруг уйдет в бесконечный цикл на ожидании из ранд числа, меньше границы.
                  Ответить
                  • > уйдет в бесконечный цикл
                    Если у генератора равномерное распределение - не уйдет.
                    Ответить
                    • Ну если в соседнем потоке кто-то будет срандить некий один и тот же неудачный сиид, то вполне может.
                      Ответить
                • Ну это будет уже отображение не X → Y, а X − Z → Y.
                  Против математики не попрёшь :)
                  Ответить
              • А вы видите диапазоны или точки, которые перераспределяются не туда? Просто интересно что не учтено. Но даже по результатам Теста Борманда довольно близко к нормальному.
                Ответить
                • Да, вижу. Таких диапазонов там почти треть ;)

                  У 32 чисел вероятность 0.00997, а у остальных 0.01001
                  Ответить
                  • А можно прямо на конкретных точках, улетающих не туда?
                    Ответить
                    • Суть тут в том, что никак нельзя раскидать 32768 шаров в 100 корзинок поровну. В каких-то всяко будет больше. Это мы и видим в выводе проги.

                      Из-за этого, например, 0 выпадает чаще чем 2. Это, конечно, копейки. Но вот для всяких научных расчетов, лотерей и тому подобного - это совершенно неприемлимо.
                      Ответить

    Добавить комментарий