Usando / dev / random, / dev / urandom per generare dati casuali


12

Sto cercando modi per usare /dev/random(o /dev/urandom) dalla riga di comando. In particolare, vorrei sapere come utilizzare un flusso tale stdinda scrivere flussi di numeri casuali su stdout(un numero per riga).

Sono interessato a numeri casuali per tutti i tipi numerici che l'architettura della macchina supporta in modo nativo. Ad esempio, per un'architettura a 64 bit, questi includono numeri interi con segno e senza segno a 64 bit e numeri in virgola mobile a 64 bit. Per quanto riguarda gli intervalli, lo faranno gli intervalli massimi per i vari tipi numerici.

So come fare tutto questo con interpreti per tutti gli usi come Perl, Python, ecc., Ma mi piacerebbe saperlo fare con strumenti "più semplici" dalla shell. (Per "più semplice" intendo "più probabilità di essere disponibile anche in un'installazione Unix molto minimale".)

Fondamentalmente il problema riduce quello della conversione dei dati binari nelle loro rappresentazioni di stringa sulla riga di comando. (Ad esempio, questo non farà:. printf '%f\n' $(head -c8 /dev/random))

Sto cercando risposte agnostiche alla shell. Inoltre, la differenza tra /dev/randome /dev/urandomnon è importante per questa domanda. Mi aspetto che qualsiasi procedura che funzioni per uno funzionerà per l'altro, anche quando la semantica dei risultati potrebbe differire.


Ho adattato la risposta di EightBitTony per produrre le funzioni toints, ecc. Mostrate di seguito.

Esempio di utilizzo:

% < /dev/urandom toprobs -n 5
0.237616281778928
0.85578479125532
0.0330049682019756
0.798812391655243
0.138499033902422

Osservazioni:

  1. Sto usando hexdumpinvece odperché mi ha dato un modo più semplice per formattare l'output nel modo desiderato;
  2. Purtroppo, hexdumpnon supporta numeri interi a 64 bit (wtf ???);
  3. L'interfaccia delle funzioni ha bisogno di lavoro (es. Dovrebbero accettare -n5e anche -n 5), ma data la mia pietosa abilità di programmazione della shell, questa è stata la migliore che ho potuto mettere insieme rapidamente. (Commenti / miglioramenti sono benvenuti, come sempre.)

La grande sorpresa che ho avuto da questo esercizio è stata scoprire quanto sia difficile programmare sulla shell le cose numeriche più elementari (ad esempio leggere un float esadecimale o ottenere il massimo valore float nativo) ...


_tonums () {
  local FUNCTION_NAME=$1 BYTES=$2 CODE=$3
  shift 3

  local USAGE="Usage: $FUNCTION_NAME [-n <INTEGER>] [FILE...]"
  local -a PREFIX

  case $1 in
    ( -n ) if (( $# > 1 ))
           then
               PREFIX=( head -c $(( $2 * $BYTES )) )
               shift 2
           else
               echo $USAGE >&2
               return 1
           fi ;;
    ( -* ) echo $USAGE >&2
           return 1 ;;
    (  * ) PREFIX=( cat ) ;;
  esac

  local FORMAT=$( printf '"%%%s\\n"' $CODE )
  $PREFIX "$@" | hexdump -ve $FORMAT
}

toints () {
  _tonums toints 4 d "$@"
}

touints () {
  _tonums touints 4 u "$@"
}

tofloats () {
  _tonums tofloats 8 g "$@"
}

toprobs () {
  _tonums toprobs 4 u "$@" | perl -lpe '$_/=4294967295'
}

1
tr -cs '[:digit:]' '[\n*]' </dev/urandomdovrebbe darti solo un numero intero.
cuonglm,

per quanto ne so, / dev / random non genera numeri casuali di per sé, ma aggiunge rumore alle funzioni matematiche che danno un numero pseudo-casuale affinché diventino meno prevedibili. Potresti voler dare un'occhiata a randomlib.sourceforge.net
Rui F Ribeiro


Hai bisogno di casualità di qualità crittografica o, ad esempio, la semina basata sul tempo è abbastanza buona?
Gilles 'SO-smetti di essere malvagio' il

@Gilles: la motivazione della mia domanda era più quella di scoprire gli strumenti di shell e Unix che la casualità; Volevo solo sapere quali strumenti Unix di base esistevano per convertire un flusso di dati binari nella loro rappresentazione di stringhe.
kjo

Risposte:


21

È possibile utilizzare odper ottenere numeri da /dev/randome /dev/urandom.

Per esempio,

Numeri interi decimali senza segno a 2 byte,

$ od -vAn -N2 -tu2 < /dev/urandom
24352

Intero decimale con segno 1 byte,

$ od -vAn -N1 -td1 < /dev/urandom
-78

Numeri interi decimali senza segno a 4 byte,

$ od -vAn -N4 -tu4 < /dev/urandom
3394619386

man odper ulteriori informazioni su od.


8

Alcune shell (ad es. bash(1)) Hanno una $RANDOM"variabile" che fornisce numeri casuali.


1

Potresti fare qualcosa del tipo:

perl -le '
  while (q(
    c char,  C unsigned char, s! short, S! unsigned short,
    i! int,  I! unsigned int, l! long,  L! unsigned long,
    f float, d double,) =~ /(\S+) (.*?),/gs) {
    $size = length(pack $1, 0);
    sysread STDIN, $data, $size;
    print "$2($size): " . unpack($1, $data);
  }' < /dev/urandom

Che su un sistema a 64 bit ti darebbe qualcosa del tipo:

char(1): -98
unsigned char(1): 62
short(2): -12526
unsigned short(2): 399
int(4): 499066219
unsigned int(4): 2312134917
long(8): -4889591208978026255
unsigned long(8): 2080566823379835456
float(4): 55.4727554321289
double(8): 8.6395690272822e-05
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.