Вопрос или проблема
Мне нужно сгенерировать несколько 64-битных знаковых целых чисел для тестирования.
Как я могу это сделать?
#!/bin/sh
long=$(????)
Объедините 2 32-битных целых числа, полученных из /dev/urandom
. Должно быть возможно использовать od
, чтобы захватить одно 64-битное значение в соответствии с ответом Стефана, но в некоторых версиях OS X это не работает без соответствующего сообщения об ошибке.
#!/bin/sh
low32=$(od -An -td4 -N4 < /dev/urandom)
high32=$(od -An -td4 -N4 < /dev/urandom)
long=$(($low32 + ($high32 << 32) ))
macOS поставляется с Python. Используйте его random
модуль.
python -c 'import random; rng = random.SystemRandom(); print rng.randint(-2**63, 2**63-1)'
Если вам не нужны безопасные случайные числа, это можно упростить до
python -c 'import random; print(random.randint(-2**63, 2**63-1))'
Поскольку macOS имеет /dev/urandom
, вы можете сделать следующее:
od -An -vtd8 -N8 < /dev/urandom
Однако, согласно словам тех, кто пробовал это на реальной системе macOS (см. комментарии), это там не работает. Поскольку macOS предназначен быть сертифицированной Unix-системой, это означает, что это ошибка, так как POSIX четко определяет поведение этой команды. Единственное, что POSIX оставляет неопределенным (определяется реализацией) – это порядок байтов (что здесь нам не интересно, так как это все случайные байты).
В качестве альтернативы, вы можете использовать ksh
/bash
/zsh
‘s $RANDOM
здесь. Несмотря на то, что sh
в macOS сейчас основан на bash
, лучше переключиться на bash/zsh (или реализации ksh
, отличные от mksh
, чья арифметика использует 32 бита), так как $RANDOM
не является функцией sh
, поэтому может не работать в будущих версиях macOS, если они решат переключиться на другую оболочку.
m=32768 # диапазон $RANDOM
long=$((RANDOM+RANDOM*m+RANDOM*m*m+RANDOM*m*m*m+RANDOM*m*m*m*m))
или:
long=$((RANDOM|(RANDOM<<15)|(RANDOM<<30)|(RANDOM<<45)|(RANDOM<<60)))
Это 5*15 == 75 бит, но это будет обрезано до 64 бит оболочкой.
В инструментариуме POSIX способ сгенерировать случайные числа – использовать awk
‘s rand()
, так что вы можете сделать:
awk 'BEGIN{srand(); printf "%.20g\n", rand() * (2^64) - (2^63)}'
Однако будьте осторожны, что во многих реализациях awk
(тех, которые основывают семя srand()
на результате time(3)
), вы получите одинаковый вывод, если запустите это дважды за одну и ту же секунду.
Также, из-за способа представления чисел с плавающей запятой, я ожидаю, что некоторые 64-битные числа (такие как 263-1) никогда не будут выведены.
Вы можете объединить два 32-битных числа, например,
#!/bin/bash
printf '0x%04x%04x\n' $RANDOM $RANDOM
j=$(printf '16#%04x%04x' $RANDOM $RANDOM)
echo $j
echo $(($j))
Пример вывода
0x5e34562d
16#7cf567f9
2096457721
Это одна из многих функций, возникших в оболочке Korn (ksh), которые были скопированы в bash и zsh спустя несколько лет.
Согласно комментарию – вы можете добавить дополнительные биты:
#!/bin/bash
printf '0x%04x%04x\n' $RANDOM $RANDOM
foo=32767
printf '%016x\n' $((foo << 49))
printf '%016x\n' $((foo << 34))
printf '%016x\n' $((foo << 19))
printf '%016x\n' $((foo << 4))
printf '%016x\n' $((foo % 16))
printf '%016x\n' $((foo << 49 |
(foo << 34) |
(foo << 19) |
(foo << 4) |
(foo % 16)))
printf '%d\n' $((foo << 49 |
(foo << 34) |
(foo << 19) |
(foo << 4) |
(foo % 16)))
Пример вывода:
0x3a1e1184
fffe000000000000
0001fffc00000000
00000003fff80000
000000000007fff0
000000000000000f
ffffffffffffffff
-1
Ответ или решение
Для генерации случайного 64-битного целого числа со знаком на macOS можно использовать несколько различных методов, включая как встроенные утилиты оболочки, так и язык программирования Python. В этой статье мы рассмотрим несколько подходов к решению этой задачи, обращая внимание на детали и особенности каждого метода.
1. Использование /dev/urandom
и od
Одним из способов является считывание случайных байтов из специального файла /dev/urandom
, который предоставляет доступ к генератору случайных чисел. Используя утилиту od
, мы можем извлечь последовательность байт и скомбинировать их в 64-битное целое число.
#!/bin/sh
low32=$(od -An -td4 -N4 < /dev/urandom)
high32=$(od -An -td4 -N4 < /dev/urandom)
long=$(($low32 + ($high32 << 32)))
echo $long
Пояснение: В этом скрипте мы считываем два 32-битных целых числа, одно — из младших 32 бит, другое — из старших. Затем комбинируем их с помощью побитового сдвига.
2. Использование Python
На любой macOS установлен интерпретатор Python, который позволяет легко генерировать случайные числа с использованием модуля random
. С помощью этого модуля можно получить более безопасные случайные числа.
Для стандартной библиотеки Python можно воспользоваться следующим кодом:
python -c 'import random; print(random.randint(-2**63, 2**63-1))'
Объяснение: Здесь мы используем функцию randint
, чтобы сгенерировать случайное целое число в диапазоне от -2^63 до 2^63-1, что соответствует 64-битному знаковому диапазону.
3. Подход с использованием $RANDOM
Также можно воспользоваться встроенной переменной $RANDOM
в оболочке bash или zsh. Эта переменная генерирует случайные числа от 0 до 32767 и, комбинируя несколько таких значений, можно получить 64-битное число.
#!/bin/bash
m=32768 # диапазон $RANDOM
long=$((RANDOM + RANDOM*m + RANDOM*m*m + RANDOM*m*m*m + RANDOM*m*m*m*m))
echo $long
Замечание: Этот метод вызывает $RANDOM
пять раз, что дает в сумме 75 бит, но truncation до 64 бит осуществляется автоматически.
4. Использование AWK
Если вы предпочитаете использовать awk
, можно воспользоваться встроенной функцией rand()
, хотя следует помнить о некоторых ограничениях, связанных с тем, как функция srand()
инициализирует генератор случайных чисел.
awk 'BEGIN{srand(); printf "%.0f\n", rand() * (2^64) - (2^63)}'
Преимущество: Этот метод также достаточно прост и может быть полезен, если у вас под рукой только awk
.
Заключение
В зависимости от ваших требований к безопасности и сложности задачи, любой из вышеперечисленных методов можно использовать для генерации случайных 64-битных знаковых целых чисел. Обратите внимание, что генерируемые числа могут не обеспечивать криптографической стойкости, если вы не используете специализированные методы генерации, такие как random.SystemRandom()
в Python. Выбор подхода зависит от ваших конкретных нужд и окружения.