Как я могу сгенерировать случайное 64-битное знаковое целое число в macOS?

Вопрос или проблема

Мне нужно сгенерировать несколько 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. Выбор подхода зависит от ваших конкретных нужд и окружения.

Оцените материал
Добавить комментарий

Капча загружается...