Случайные числа с помощью C#

Я смотрю на генерацию случайного числа между 1 и 5 миллионов. Процесс не должен быть быстрым (хотя было бы хорошо, если бы это было), но это должно быть максимально случайно (я знаю, что ничто не случайно). У меня есть множество источников данных для семени.

Я не уверен, будет ли .NETСлучайныйкласс достаточно хорошим для этого.

Это будет использоваться для выбора выигрышного билета.

11
задан Peter Mortensen 17 May 2015 в 18:49
поделиться

6 ответов

Класс System.Random , вероятно, достаточно хорош:

Выбраны псевдослучайные числа с равной вероятностью из конечного набора чисел. Выбранные числа не являются полностью случайными, поскольку для их выбора используется определенный математический алгоритм, но они достаточно случайны для практических целей. Текущая реализация класса Random основана на алгоритме генератора случайных чисел Дональда Э. Кнута. Для получения дополнительной информации см. D. E. Knuth. «Искусство компьютерного программирования, том 2: получисловые алгоритмы». Addison-Wesley, Reading, MA, второе издание, 1981.

Единственное, на что вам нужно обратить внимание, это то, что вы не должны повторно использовать одно и то же семя слишком часто:

Если одно и то же семя используется повторно, то генерируется такая же серия чисел. Один из способов создания разных последовательностей - сделать начальное значение зависимым от времени, тем самым создавая разные серии с каждым новым экземпляром Random.

17
ответ дан 3 December 2019 в 01:20
поделиться

Принципиально это не имеет значения, такие minutiae на самом деле не влияет на то, является ли что-то «pythonic» или нет.

Если вы заинтересованы в пустяках, однако, есть некоторые различия.

  1. Строительный логический тип не существовал до Python 2.3 , поэтому код, предназначенный для запуска в древних версиях, имеет тенденцию использовать форму , в то время как форма 1: . Вы увидите его, например, в стандартной библиотеке.

  2. Строения True и False являются не зарезервированными словами до Python 3 , поэтому их можно назначить, изменив их значение. Это помогает в случае выше, потому что код может делать True = 1 для обратной совместимости, но означает, что имя True необходимо искать в глобальном словаре каждый раз при его использовании.

  3. Из-за вышеуказанного ограничения байт-код двух версий компиляции на отличается в Python 2 так как существует оптимизация для постоянных целых чисел, которые он не может использовать для True . Поскольку Python может сказать при компиляции 1 , что он всегда ненулевой, он удаляет условный скачок и вообще не загружает константу:

     > > > import dis
    > > > def while_1 ():
    ... в то время как 1:
    ... проход
    ...
    > > > def while_true ():
    ... пока True:
    ... проход
    ...
    > > > dis.dis (while_1)
    2 0 SETUP_LOOP 5 (до 8)
    
    3 > > 3 JUMP_ABSOLUTE 3
    6 POP_TOP
    7 POP_BLOCK
    > > 8 LOAD_CONST 0 (Нет)
    11 RETURN_VALUE
    > > > dis.dis (while_true)
    2 0 SETUP_LOOP 12 (до 15)
    > > 3 LOAD_GLOBAL 0 (Истина)
    6 JUMP_IF_FALSE 4 (до 13)
    9 POP_TOP
    
    3 10 JUMP_ABSOLUTE 3
    > > 13 POP_TOP
    14 POP_BLOCK
    > > 15 LOAD_CONST 0 (Нет)
    18 RETURN_VALUE
    

Итак, в то время как True: немного проще для чтения, и в то время как 1: немного добрее к старым версиям Python. Поскольку вам вряд ли нужно запускать на Python 2.2 в эти дни или нужно беспокоиться о количестве байт-кодов ваших петель, первый немного предпочтительнее.

-121--2103037-

Это код, который вам нужен:

    protected override void OnPaint( PaintEventArgs e )
    {
        using ( var bmp = new Bitmap( 100, 100 ) )
        using ( var g = Graphics.FromImage( bmp ) )
        using ( var ia = new ImageAttributes() )
        {
            // 1. create a sample bitmap
            g.Clear( Color.White );
            var p = Point.Empty;
            foreach ( var color in new Color[] { Color.Black, Color.Gray, Color.LightBlue, Color.Green, Color.Red, Color.Magenta } )
                using ( var brush = new SolidBrush( color ) )
                {
                    g.DrawString( "Some sample text", SystemFonts.DefaultFont, brush, p );
                    p.Offset( 0, 16 );
                }
            // 2. transfer the bitmap on screen
            e.Graphics.DrawImage( bmp, Point.Empty );
            // 3. transfer a part of the bitmap on screen again, this time removing all blue
            ia.SetColorMatrix( new ColorMatrix( new float[][] {
                        new float[] {1, 0, 0, 0, 0},
                        new float[] {0, 1, 0, 0, 0},
                        new float[] {0, 0, 0, 0, 0},
                        new float[] {0, 0, 0, 1, 0},
                        new float[] {0, 0, 0, 0, 1}} ) );
            e.Graphics.DrawImage(
                bmp,
                new Rectangle( 30, 0, 40, 100 ),
                30, 0, 40, 100,
                GraphicsUnit.Pixel,
                ia );
        }
    }
-121--4195996-

Если вы ищете истинные случайные числа, то вам следует рассмотреть возможность использования онлайн-генератора случайных чисел, который использует естественное явление, такое как http://www.random.org , который использует атмосферный шум. Истинные случайные числа также делают хорошие семена для генераторов psuedo-случайных чисел.

Сипвиз показывает, как использовать его в C # в своем ответе: Генерировать случайные значения в C # . Это также обсуждается здесь: http://www.vcskicks.com/random-number-generator.php .

Существует много углов к генераторам случайных чисел. Интересной альтернативной реализацией является ISSAC (ttp ://burtleburtle.net/bob/rand/isaac.html), которая также содержит хорошее обсуждение предвзятости и таковых, и также существует версия C # ( http://burtleburtle.net/bob/rand/isaacafa.html ).

1
ответ дан 3 December 2019 в 01:20
поделиться

Если вам нужно криптографическое случайное число, воспользуйтесь классом System.Security.Cryptography.RNGCryptoServiceProvider или RandomNumberGenerator. Create () фабричный метод для создания настроенного по умолчанию генератора случайных чисел.

7
ответ дан 3 December 2019 в 01:20
поделиться

Я только что написал небольшой образец приложения с использованием JQuery 1.4.1 и UI 1.8rc1. Все, что я сделал, это указал конструктор как:

var theDialog = $(".mydialog").dialog({
        autoOpen: false,
        resizable: false,
        modal: true,
        width:'auto'
});

Я знаю, вы сказали, что это заставляет его занять 100% ширину окна браузера, но он работает сладко здесь, протестирован в FF3.6, Chrome и IE8.

Я не делаю вызовы AJAX, просто вручную меняю HTML диалога, но не думаю, что это вызовет какие-либо пробы. Может ли какая-то другая настройка CSS выбить это?

Единственная проблема с этим заключается в том, что она делает ширину вне центра, но я нашел этот билет поддержки , где они предоставляют обходной путь размещения диалог («открыть») оператор в setTimeout для устранения проблемы.

Вот содержимое моей головы тэга:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
<script type="text/javascript" src="jquery-ui.min.js"></script>
<link href="jquery-ui.css" rel="stylesheet" type="text/css" />
<script type="text/javascript">
    $(function(){
        var theDialog = $(".mydialog").dialog({
            autoOpen: false,
            resizable: false,
            modal: true,
            width: 'auto'
        });

        $('#one').click(function(){
            theDialog.html('some random text').dialog('open');
        });

        $('#two').click(function(){
            theDialog.html('<ul><li>Apple</li><li>Orange</li><li>Banana</li><li>Strawberry</li><li>long text string to see if width changes</li></ul>').dialog('open');
        });

        $('#three').click(function(){
            //this is only call where off-centre is noticeable so use setTimeout
            theDialog.html('<img src="./random.gif" width="500px" height="500px" />');
            setTimeout(function(){ theDialog.dialog('open') }, 100);;
        });
     });
</script>

Я загрузил js и css для пользовательского интерфейса Jquery с http://jquery-ui.googlecode.com/files/jquery-ui-1.8rc1.zip . и тело:

<div class='mydialog'></div>
<a href='#' id='one'>test1</a>
<a href='#' id='two'>test2</a>
<a href='#' id='three'>test3</a>
-121--3474306-

Я бы пошел на:

def parse_int(s, base=10, val=None):
 if s.isdigit():
  return int(s, base)
 else:
  return val

Но это более или менее то же самое.

-121--1018235-

На самом деле была действительно хорошая статья, которую я прочитал довольно недавно, о различных типах PRNG и о том, как они общаются с точки зрения нескольких различных тестов случайности. К сожалению, я не могу найти его сейчас. Суть его, однако, заключалась в том, что генераторы случайных чисел по умолчанию почти на каждом популярном языке программирования довольно наивны и имеют довольно значительные уклоны.

В другом ответе уже упоминается, что ни один PRNG вообще, каким бы сложным ни был алгоритм, достаточно хорош для криптографических приложений. Это правда. Раз уж вы упомянули, что это будет использовано для «выбора выигрышного билета», давайте пока это игнорировать.

Алгоритм Knuth, используемый классом .NET System.Random , оптимизирован главным образом для быстрого, а не случайного распределения. Он является достаточно случайным для многих целей, от которых большинство приложений никогда не отходят слишком далеко, но в областях (а) игр и (б) статистического моделирования большинство людей, кажется, думают, что это плохой выбор. Это лучше, чем LCG, которые раньше были по умолчанию в старых библиотеках, но вы все равно не хотите использовать его для чего-то вроде лото.

Не обманывайтесь, думая, что вы просто используете криптоисточник. Проблема crypto RNG в том, что они заполняют поток байтов, но превращение этого в одно случайное целое число между x и y требует, чтобы вы сделали какую-то модульную арифметику (или округление - тот же результат либо путь). И если ваш случайный диапазон не делится совершенно равномерно на любую степень 2, определяемую длиной байта, то вы получите уклон в нижних числах. Сгенерированные данные имеют высокую энтропию, но результат будет смещен.

В качестве простого примера скажем, что вы получаете «совершенное» случайное число от 1 до 10 и теперь вы хотите превратить его в случайное число между 1 и 7. Как ты это делаешь? Простой расчет результата% 7 будет сильно смещен к числам 1-3.Есть несколько способов уменьшить смещение при использовании криптографического RNG, но я пытаюсь сказать, что криптографические RNG предназначены для криптоприложений, и использование одного из них для моделирования Монте-Карло обычно не является лучшей идеей.

Насколько мне известно, самым популярным «хорошим» PRNG на сегодняшний день, который обычно используется в игровых приложениях, является Mersenne Twister . Здесь реализована .NET . Этот алгоритм проходит все тесты Diehard Tests для случайного распределения; он почти не показывает уклона и является хорошим выбором, когда вы используете случайные числа для вероятностных и статистических приложений.

Научная библиотека GNU также имеет ряд алгоритмов RNG и, что неудивительно, Mersenne Twister находится в верхней части списка. Некоторые из других, однако, стоит посмотреть ради любопытства; RANLUX также набирает довольно высокие баллы в тесте DIRC.

Эрик прав со своим комментарием, конечно; вся эта информация сводится на нет, если у вас нет конкретных технических требований относительно того, насколько случайными должны быть ваши случайные числа. Я использую определение, которое было бы применимо к относительно малоэффективному игорному/игровому приложению (то есть не крупному зарегистрированному игорному сайту с миллионами посетителей в день - для них существуют более строгие правила случайности).

5
ответ дан 3 December 2019 в 01:20
поделиться

См. запись в блоге Джона Скита Revisiting Randomness - очень хороший обзор того, как использовать Randomness:

Revisiting randomness
Почти каждый вопрос на Stack Overflow, который включает в себя слова "random" и "random". включает слова "случайный" и "повторяющийся", имеет один и тот же базовый ответ. Это одна из самых распространенных "загвоздок" в .NET, Java и, несомненно, в других платформах: создание нового генератора случайных генератора случайных чисел без указания семени, будет зависеть от текущего момента времени. Текущее время, как измеряемое компьютером, не меняется очень часто по сравнению с тем, как часто вы можете создавать и использовать генератор случайных генератор случайных чисел - то есть код, который многократно создает новый экземпляр Random и использует его один раз, в конечном итоге покажет большое количество повторений.

подробнее...

5
ответ дан 3 December 2019 в 01:20
поделиться

.NET Random подойдет для этого:

var random = new Random(System.DateTime.Now.Millisecond);

int randomNumber = random.Next(1, 5000000);
0
ответ дан 3 December 2019 в 01:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: