Math.random () по сравнению с Random.nextInt (интервал)

Чтобы найти все страницы от первой страницы до последней страницы по идентификатору книги, ПРОСТАВЬТЕ номера своих страниц от STRING до INTEGER, затем добавляйте +1 к каждому номеру страницы, пока не дойдете до последней страницы.

Сначала, превратите вашу исходную таблицу в переменную таблицы с типами данных Integer, используя TRY_CAST.

DECLARE @Book TABLE (
    [ID]        INT
   ,[FirstPage] INT
   ,[LastPage]  INT
)

INSERT INTO @Book
SELECT  [ID]
       ,TRY_CAST(RIGHT([FirstPage], 3) AS int) AS [FirstPage]
       ,TRY_CAST(RIGHT([LastPage], 3) AS int)  AS [LastPage]
FROM [YourOriginalTable]

Установите максимальную страницу, на которую ваши страницы будут увеличиваться, используя переменную. Это сведет ваши результаты к правильному количеству страниц. В противном случае ваша таблица будет иметь гораздо больше строк, чем вам нужно.

DECLARE @LastPage   INT 
SELECT @LastPage = MAX([LastPage]) FROM @Book

Для преобразования таблицы из трех столбцов (идентификатор, первая страница, последняя страница) в таблицу из двух столбцов (идентификатор, страница) потребуется UNPIVOT.

Мы убираем этот UNPIVOT в CTE (Общее выражение таблицы: в основном, умная версия временной таблицы (например, #TempTable или @TableVariable, но которую вы можете использовать только один раз, и в некоторых случаях она немного более эффективна) обстоятельства).

В дополнение к UNPIVOT ваших столбцов [Имя] и [Фамилия] в большую таблицу, мы собираемся добавить любую другую комбинацию номера страницы для каждого идентификатора, используя UNION ALL.

;WITH BookCTE AS (
    SELECT [ID]
          ,[Page]
    FROM (SELECT [ID]
                ,[FirstPage]
                ,[LastPage]
          FROM @Book) AS bp
    UNPIVOT
    (
        [Page] FOR [Pages] IN ([FirstPage], [LastPage])
    ) AS up
    UNION ALL
    SELECT [ID], [Page] + 1 FROM BookCTE WHERE [Page] + 1 < @LastPage
)

Теперь, когда ваши данные хранятся в табличном формате с использованием CTE со всеми комбинациями [ID] и [Page] вплоть до максимальной страницы в вашей таблице @Book, пришло время присоединиться к вашему CTE с таблицей @Book.

SELECT DISTINCT
        cte.ID
       ,cte.Page
FROM BookCTE AS cte
    INNER JOIN @Book AS bk
        ON bk.ID = cte.ID
WHERE cte.Page <= bk.[LastPage]
ORDER BY
       cte.ID
      ,cte.Page
OPTION (MAXRECURSION 10000)

См. также:

127
задан Gili 10 April 2009 в 19:29
поделиться

3 ответа

Вот подробное объяснение почему " Random.nextInt (n) и более эффективен, и менее предвзят, чем Math.random () * n "из поста на форумах Sun, на который ссылается Гили:

Math.random () использует Random.nextDouble () для внутреннего использования.

Random.nextDouble () дважды использует Random.next (), чтобы сгенерировать дубль, который имеет приблизительно равномерно распределенные биты в своей мантиссе, поэтому он равномерно распределен в диапазоне от 0 до 1- (2 ^ -53).

Random.nextInt (n) использует Random.next () в среднем менее чем в два раза - он использует его один раз, и если полученное значение выше максимального кратного n ниже MAX_INT, он пытается снова, в противном случае возвращает значение по модулю n ( это предотвращает перекос распределения значений выше максимального кратного n ниже MAX_INT), таким образом, возвращая значение, которое равномерно распределено в диапазоне от 0 до n-1.

Перед масштабированием на 6 вывод Math.random () является одним из 2 ^ 53 возможных значений, полученных из равномерного распределения.

Масштабирование на 6 не изменяет количество возможных значений, и приведение к int затем приводит к принудительному переводу этих значений в одно из шести «сегментов» (0, 1, 2, 3, 4, 5), каждое из которых соответствует диапазоны, охватывающие 1501199875790165 или 1501199875790166 из возможных значений (так как 6 не является диспозитором 2 ^ 53). Это означает, что для достаточного количества бросков игральных костей (или кристалла с достаточно большим числом сторон) штамп покажет себя смещенным в сторону больших ведер.

Вы будете очень долго ждать бросания костей для этот эффект, чтобы показать.

Math. Функция random () также требует примерно вдвое больше обработки и подлежит синхронизации.

164
ответ дан 24 November 2019 в 00:46
поделиться

еще одним важным моментом является то, что Random.nextInt (n) повторяется, так как вы можете создать два объекта Random с помощью то же семя. Это невозможно с помощью Math.random ().

27
ответ дан 24 November 2019 в 00:46
поделиться

Согласно https://forums.oracle.com/forums/thread.jspa?messageID=6594485& # 6594485 Random.nextInt (n) более эффективен и менее предвзят, чем Math.random () * n

14
ответ дан 24 November 2019 в 00:46
поделиться
Другие вопросы по тегам:

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