Получение случайного целого числа <u64> в AssemblyScript

В книге AssemblyScript упоминается, что Math.random() принимает начальное значение и возвращает значение <f64>. Мне просто нужно случайное значение <u64>. Как мне этого добиться?

Я попытался

(Math.random() * 0xffffffffffffffff) as u64
<u64>(<f64>Math.random() * <f64>0xffffffffffffffff)
(<f64>Math.random() * <f64>0xffffffffffffffff) as u64

или с f64.MAX_VALUE вместо 0xffffffffffffffff и еще много чего.

но я продолжаю получать 0.

Я могу получить <U32> случайные значения просто отлично, но когда я умножаю два <U32> случайных значения, я получаю около 52 случайных битов, а остальное равно 0. Я понимаю, почему это происходит из моего фона JS, все еще из типизированной структуры и абстракций более низкого уровня AS I надеялся, что трений не будет.

Как именно я могу правильно получить <u64> случайное целое число с помощью AssemblyScript?

Редактировать:

Я думаю, что наконец-то сделал это так, как

(<u64>(Math.random() * u32.MAX_VALUE) << 32) | <u32>(Math.random() * u32.MAX_VALUE)

но так ли это на самом деле?

Использование u32.random в качестве соломенного человека для случайного u32: сработает ли ((u32.random() as u64) << 32) | (u32.random as u64)? Или побитовые операторы AssemblyScript работают только с 32-битными числами, как в JS?

Bbrk24 17.11.2022 20:39

@ Bbrk24 Нет ... только что проверил ((<u32>Math.random() << 32) * 0xffffffffffffffff) as u64 все еще дает 0.

Redu 17.11.2022 20:47

Вы уверены, что <u32>Math.random() работает? Math.random() генерирует в диапазоне [0, 1), который всегда будет давать 0 при преобразовании в целое число. Я представлял, что u32.random больше похож на <u32>(Math.random() * <f64>0xffffffff).

Bbrk24 17.11.2022 21:02

@Bbrk24 Bbrk24 Я не конвертирую Math.random() в целое число, пока не умножу его на достаточно большое число, и да, <u32>(Math.random() * u32.MAX_VALUE) просто отлично работает.

Redu 17.11.2022 21:10

Вот что я имел в виду под u32.random. Я просто использовал его как сокращение, так как не знал точного синтаксиса/реализации.

Bbrk24 17.11.2022 21:33

@ Bbrk24 Bbrk24 Теперь я понял вашу точку зрения в вашем первом комментарии, но со всеми этими типами и всем остальным я думаю, что должен быть более простой способ. Почему бы вам не выполнить эту операцию сразу в 64-битной среде? Особенно Math.random() * 0xffffffffffffffff получение 0 сбивает с толку, учитывая, что Math.random() возвращает <f64>. Возможно, ошибка или что-то, чего мне очень не хватает в общем двоичном представлении чисел.

Redu 17.11.2022 22:12
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
88
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Прочитав ваш вопрос, я решил изучить, как AssemblyScript реализует Math.random в стандартной библиотеке , чтобы посмотреть, смогу ли я получить вдохновение для решения вашей проблемы.

Забавно, кажется, что он использует murmurhash3 и некоторые дополнительные хэши. Прямо перед возвратом он переинтерпретирует значение u64 в f64 после некоторой дополнительной обработки:

    let r = (s0 >> 12) | 0x3FF0000000000000;
    return reinterpret<f64>(r) - 1;

Мне стало любопытно, можем ли мы использовать это значение u64 напрямую как число в случайной последовательности, поэтому я переработал задействованные биты и разместил их на github здесь, но основная функция такова:

export function randomU64(): u64 { // see: v8/src/base/utils/random-number-generator.cc
  if (!random_seeded) seedRandom(reinterpret<i64>(0)); // TODO: for now, the seed is always 0.
  let s1 = random_state0_64;
  let s0 = random_state1_64;
  random_state0_64 = s0;
  s1 ^= s1 << 23;
  s1 ^= s1 >> 17;
  s1 ^= s0;
  s1 ^= s0 >> 26;
  random_state1_64 = s1;
  return s0;
}

Очень краткий тест показывает, что, по крайней мере, на первый взгляд, он дает довольно хорошие случайные результаты:

Test randomU64 distribution. All values should be fairly close.
Map(19) {
  0n => 987,
  1n => 495, -1n => 515, 2n => 542, -2n => 489,
  3n => 518, -3n => 495, 4n => 479, -4n => 510,
  5n => 513, -5n => 497, 6n => 473, -6n => 505,
  7n => 468, -7n => 528, 8n => 501, -8n => 472,
  9n => 519, -9n => 494
}

Спасибо за вашу попытку. Это интересно. Я должен проверить функцию .popcnt(), чтобы увидеть, получим ли мы 32 в среднем за несколько попыток для ввода типа <u64>. Я думаю, что функциональность seedRandom() реализуется так же, как (Math.random() * Date.now()) as u64.

Redu 27.11.2022 19:51

Я не думал о popcnt для случайности. Он получает 31.9805 среднее значение popcnt для следующих 10000 значений, так что кажется достаточно близким. Я отправил еще один тест в репо.

TachyonicBytes 27.11.2022 23:32

Выглядит хорошо, но, поскольку мы всегда начинаем с 0, что дает золотое сечение, это довольно детерминировано. Чтобы внести некоторую энтропию, я перефразировал строку 36 в репозитории if (!random_seeded) seedRandom(reinterpret<i64>(Math.random()*<f64>Date.now()));‌​. Теперь даже после перекомпиляции мы получаем разные случайные числа. Стандартное отклонение и среднее значение 10 тестов с 1e6 x 64-битными popcnts составляют 0,0059% и 32,0019481 соответственно.

Redu 28.11.2022 12:09

Другие вопросы по теме