почему семя на 48 битов в util Случайном классе?

Почему этот класс использует семя на 48 битов в своей линейной формуле конгруэтности? Я ожидал бы 32 или 64...

Я знаю, что это берет биты высшего порядка при просьбе относительно 32 битовых значений. Но почему еще только 16 дополнительных битов? Действительно ли это был "случайный" выбор?

9
задан Pete Kirkham 14 February 2010 в 10:57
поделиться

3 ответа

Да. Вот способ сделать это без битового числа в lg (n) , если вы знаете, что рассматриваемое целое число является степенью 2.

unsigned int x = ...;
static const unsigned int arr[] = {
  // Each element in this array alternates a number of 1s equal to
  // consecutive powers of two with an equal number of 0s.
  0xAAAAAAAA, // 0b10101010..         // one 1, then one 0, ...
  0xCCCCCCCC, // 0b11001100..         // two 1s, then two 0s, ...
  0xF0F0F0F0, // 0b11110000..         // four 1s, then four 0s, ...
  0xFF00FF00, // 0b1111111100000000.. // [The sequence continues.]
  0xFFFF0000
}

register unsigned int reg = (x & arr[0]) != 0;
reg |= ((x & arr[4]) != 0) << 4;
reg |= ((x & arr[3]) != 0) << 3;
reg |= ((x & arr[2]) != 0) << 2;
reg |= ((x & arr[1]) != 0) << 1;

// reg now has the value of lg(x).

В каждом из шагов reg | = последовательно проверяется, являются ли какие-либо биты x общими с чередующимися битовыми масками в arr . Если они есть, это означает, что lg (x) имеет биты, которые находятся в этой битовой маске, и мы эффективно добавляем 2 ^ k в reg , где k - это регистрация длины чередующейся битовой маски. Например, 0xFF00FF00 является чередующейся последовательностью 8 единиц и нулей, поэтому k является 3 (или lg (8) ) для этой битовой маски.

По существу, каждый reg | = ((x & arr [k])... шаг (и начальное назначение) проверяет, имеет ли lg (x) бит k наборов. Если да, то добавим его в рег ; сумма всех этих битов будет равна lg (x) .

Это выглядит как много магии, так что давайте попробуем пример. Предположим, мы хотим знать, что сила 2 значение 2 048:

// x = 2048
//   = 1000 0000 0000

register unsigned int reg = (x & arr[0]) != 0;
// reg =       1000 0000 0000
         & ... 1010 1010 1010
       =       1000 0000 0000 != 0
// reg = 0x1 (1)        // <-- Matched! Add 2^0 to reg.

reg |= ((x & arr[4]) != 0) << 4;
// reg =     0x .. 0800
           & 0x .. 0000
       =              0 != 0
// reg = reg | (0 << 4) // <--- No match.
// reg = 0x1 | 0
// reg remains 0x1.

reg |= ((x & arr[3]) != 0) << 3;
// reg =     0x .. 0800
           & 0x .. FF00
       =            800 != 0
// reg = reg | (1 << 3) // <--- Matched! Add 2^3 to reg.
// reg = 0x1 | 0x8
// reg is now 0x9.         

reg |= ((x & arr[2]) != 0) << 2;
// reg =     0x .. 0800
           & 0x .. F0F0
       =              0 != 0
// reg = reg | (0 << 2) // <--- No match.
// reg = 0x9 | 0
// reg remains 0x9.        

reg |= ((x & arr[1]) != 0) << 1;
// reg =     0x .. 0800
           & 0x .. CCCC
       =            800 != 0
// reg = reg | (1 << 1) // <--- Matched! Add 2^1 to reg.
// reg = 0x9 | 0x2
// reg is now 0xb (11).

Мы видим, что конечное значение reg является 2 ^ 0 + 2 ^ 1 + 2 ^ 3, что действительно 11.

-121--3348365-

В Oracle , mysql и SQL Server могут быть очень разными даже такие простые функции, как автоматическое приращение первичного ключа.

Некоторые другие важные отличия:

  • SQL Server проводит различие между ключом кластеризации и первичным ключом; другие базы данных. Этот выбор имеет серьезные последствия для производительности.

  • SQL Server поддерживает синтаксис НАБОРОВ @ Total = Total = @ Total + Amount для быстрых вычислений таких объектов, как выполняемые итоговые значения. mysql позволяет использовать пользовательскую переменную аналогичным образом (я думаю). В других базах данных вам, вероятно, придется использовать коррелированный подзапрос. Огромная разница в производительности.

  • SQL Server может создавать «последовательные GUID» с newsequentialid . Я не уверен, какие другие базы данных имеют эту функцию, но, как и в случае с указанными выше двумя пунктами, использование традиционного GUID в отличие от последовательного или гребенчатого.

  • Oracle CONNECT BY - очень полезный и довольно уникальный синтаксис. Общие табличные выражения в SQL Server и mysql похожи, но не совпадают.

  • Поддержка функций ранжирования/упорядочивания сильно варьируется в разных базах данных. Я постоянно размещаю здесь ответы, вызывая ROW _ NUMBER . Очень много запросов гораздо труднее писать без этого - но в то же время злоупотребление ими может повредить производительности.

  • Поддержка XML по всей карте. Большинство баз данных имеют достаточно хорошую поддержку сейчас, но и синтаксис, и семантика совершенно разные на каждой платформе.

  • Обработка даты/времени может быть совершенно иной. Oracle имеет несколько различных типов, связанных с датой/временем, некоторые из которых включают информацию о часовом поясе. В общем,Oracle намного лучше, чем другие базы данных, в управлении временными данными, и имеет несколько функций, которые будут упущены при переключении. До недавнего времени в Microsoft не было типов date и time , просто datetime , что было намного труднее нормализовать.

  • Пространственные типы различаются и/или отсутствуют в различных базах данных. mysql раскрывает всю модель OpenGIS; Поддержка Microsoft немного более базовая, но все еще компетентная. Он есть у Oracle, но найти информацию на нем немного сложно, и это своего рода дополнительная надстройка. Я думаю, что DB2 начинает получать его, но поддержка все еще немного пятна.

  • mysql фактически позволяет выбрать способ хранения индекса (т.е. btree или хэш). Это также является важным критерием исполнения.

  • SQL Server позволяет создавать столбцы INCLUDE в индексе - очень важно для производительности.

  • Oracle позволяет создавать функциональные индексы, растровые индексы и т.д. Это может быть довольно трудно обернуть голову вокруг.

  • Oracle может выполнять «пропуски» в очень специфических ситуациях, что, по моему мнению, не поддерживается в других базах данных (еще). Это может повлиять на порядок упорядочения столбцов индекса.

  • SQL Server имеет типы CLR, функции и агрегаты. Очевидно, не поддерживается ни в одном другом продукте базы данных.

  • Поддержка триггера значительно варьируется. SQL Server имеет AFTER и INSTEAD OF . mysql имеет ДО и ПОСЛЕ . Все это и многое другое есть у Oracle. Все они ведут себя совершенно иначе.

Я уверен, что есть много, много других различий, но это должно дать вам по крайней мере основное представление о том, почему 5 лет опыта работы с Oracle полностью отличается от 5 лет опыта работы с SQL Server.

-121--2856380-

Вам нужно больше битов состояния, чем битов выхода, потому что природа LCG такова, что биты состояния низкого порядка вообще не очень случайны. Так что если вы хотите 32-разрядные выходы, вам нужно более 32 бит состояния.

Зачем использовать 48, а не 64? Потому что 48 достаточно, и вы проектируете это десятилетия назад , поэтому есть веские причины, чтобы не использовать больше ресурсов, чем необходимо.

4
ответ дан 4 December 2019 в 23:39
поделиться

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

Генератор случайных чисел на компьютере фактически пытается быть истинным генератором псевдослучайных чисел.

Вы можете думать о генераторе псевдослучайных чисел как о функции расширения, которая принимает на входе начальное число и затем выводит числовой поток G (начальное число) .

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

Таким образом, наличие только 32-битного начального пространства означает, что злоумышленник, желающий определить, является ли ваш поток действительно случайным (или нарушить ваш алгоритм шифрования в зависимости от генератора случайных чисел), должен пройти только 32-битное пространство ключей (начальное пространство) и попробуйте выходные данные генератора для сравнения с предоставленным вами «случайным» потоком и посмотрите, соответствует ли он. Добавление еще 16 бит значительно увеличивает диапазон в пространстве ключей (начальных чисел), что значительно затрудняет перечисление всех возможных ключей (начальных чисел).

Что касается того, почему бы не перейти на полные 64 бита ... вероятно, когда алгоритм был реализован, возможности аппаратной обработки не поддерживали 64-битные операции так эффективно, как они могут быть выполнены сегодня на современных процессорах на базе x64, поэтому они остановились на 48.

1
ответ дан 4 December 2019 в 23:39
поделиться

A Линейный конгруэнтный генератор (LCG) характеризуется тремя параметрами a , c и м . Только определенные комбинации дают максимальный период, и не все они одинаково хорошо изучены. На выбор, вероятно, повлиял обычный компромисс между сложностью и предполагаемым использованием. К счастью, класс достаточно хорошо разработан для наследования,поэтому возможны другие реализации .

1
ответ дан 4 December 2019 в 23:39
поделиться
Другие вопросы по тегам:

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