Random number generator (device)

From Rosetta Code
Revision as of 12:42, 13 November 2012 by rosettacode>RichardRussell (Added BBC BASIC)
Task
Random number generator (device)
You are encouraged to solve this task according to the task description, using any language you may know.

If your system has a means to generate random numbers involving not only a software algorithm (like the /dev/urandom devices in Unix), show how to obtain a random 32-bit number from that mechanism.

Ada

random.adb: <lang Ada>with Ada.Streams.Stream_IO; with Ada.Text_IO; procedure Random is

  Number : Integer;
  Random_File : Ada.Streams.Stream_IO.File_Type;

begin

  Ada.Streams.Stream_IO.Open (File => Random_File,
                              Mode => Ada.Streams.Stream_IO.In_File,
                              Name => "/dev/random");
  Integer'Read (Ada.Streams.Stream_IO.Stream (Random_File), Number);
  Ada.Streams.Stream_IO.Close (Random_File);
  Ada.Text_IO.Put_Line ("Number:" & Integer'Image (Number));

end Random;</lang>

BBC BASIC

Requires Windows XP or later. <lang bbcbasic> SYS "SystemFunction036", ^random%, 4

     PRINT ~random%</lang>

C

It works on systems having /dev/urandom, like GNU/Linux.

<lang c>#include <inttypes.h>

  1. include <stdio.h>
  2. include <stdint.h>

int main(int argc, char **argv) {

   uint32_t v;
   FILE *r = fopen("/dev/urandom", "r");
   if (r == NULL)
   {

perror("/dev/urandom"); return 1;

   }
   size_t br = fread(&v, sizeof v, 1, r);
   if (br < 1)
   {

fputs("/dev/urandom: Not enough bytes\n", stderr); return 1;

   }
   printf("%" PRIu32 "\n", v);
   fclose(r);
   return 0;

}</lang>

Library: BSD libc

arc4random() appeared in OpenBSD 2.1 and has spread to many BSD systems. This function runs an ARC4 random number generator that takes entropy from a kernel device. (This kernel device is sysctl kern.arandom in OpenBSD, or /dev/urandom in some other systems.)

<lang c>#include <inttypes.h> /* PRIu32 */

  1. include <stdlib.h> /* arc4random */
  2. include <stdio.h> /* printf */

int main() { printf("%" PRIu32 "\n", arc4random()); return 0; }</lang>

Library: OpenSSL

OpenSSL can generate random numbers. The default generator uses SHA1. For Unix systems, OpenSSL will gather entropy by reading a kernel device like /dev/urandom, or by using EGD, the Entropy Gathering Daemon. For other systems, OpenSSL might use a different source of entropy.

<lang c>#include <inttypes.h>

  1. include <stdio.h>
  1. include <openssl/err.h>
  2. include <openssl/rand.h>

int main() { uint32_t v;

if (RAND_bytes((unsigned char *)&v, sizeof v) == 0) { ERR_print_errors_fp(stderr); return 1; } printf("%" PRIu32 "\n", v); return 0; }</lang>

Windows

Works with: MinGW

<lang c>#include <stdio.h> /* printf */

  1. include <windows.h>
  2. include <wincrypt.h> /* CryptAcquireContext, CryptGenRandom */

int main() { HCRYPTPROV p; ULONG i;

if (CryptAcquireContext(&p, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) == FALSE) { fputs("CryptAcquireContext failed.\n", stderr); return 1; } if (CryptGenRandom(p, sizeof i, (BYTE *)&i) == FALSE) { fputs("CryptGenRandom failed.\n", stderr); return 1; } printf("%lu\n", i); CryptReleaseContext(p, 0); return 0; }</lang>

C#

<lang csharp>using System; using System.Security.Cryptography;

private static int GetRandomInt() {

 int result = 0;
 var rng = new RNGCryptoServiceProvider();
 var buffer = new byte[4];
 rng.GetBytes(buffer);
 result = BitConverter.ToInt32(buffer, 0);
 return result;

}</lang>

Forth

<lang forth>variable rnd

randoms ( n -- )
 s" /dev/random" r/o open-file throw
 swap 0 do
   dup rnd 1 cells rot read-file throw drop
   rnd @ .
 loop
 close-file throw ;</lang>

Go

In the Go library is crypto/rand, a source specified to use dev/urandom on Unix-like systems and the CryptGenRandom API on Windows. Also implemented here is a source using dev/random, if you really want it. On my system it would print a few numbers then hang until I moved the mouse or pressed some keys on the keyboard. <lang go>package main

import (

   "crypto/rand"
   "encoding/binary"
   "fmt"
   "io"
   "os"

)

func main() {

   testRandom("crypto/rand", rand.Reader)
   testRandom("dev/random", newDevRandom())

}

func newDevRandom() (f *os.File) {

   var err error
   if f, err = os.Open("/dev/random"); err != nil {
       panic(err)
   }
   return

}

func testRandom(label string, src io.Reader) {

   fmt.Printf("%s:\n", label)
   var r int32
   for i := 0; i < 10; i++ {
       if err := binary.Read(src, binary.LittleEndian, &r); err != nil {
           panic(err)
       }
       fmt.Print(r, " ")
   }
   fmt.Println()

}</lang>

Groovy

Based, necessarily, on Java solution: <lang groovy>def rng = new java.security.SecureRandom()</lang>

Test: <lang groovy>(0..4).each { println rng.nextInt() }</lang>

Output:

380425053
-1003791794
-1972330603
1152610574
714616658

J

Untested: <lang j>256#.a.i.1!:11'/dev/urandom';0 4</lang>

Fallback: <lang j>256#.a.i.4{.host'dd if=/dev/urandom bs=4 count=1'</lang>

Note: this assumes that J is running on linux.

Java

<lang java>import java.security.SecureRandom;

public class RandomExample { public static void main(String[] args) { SecureRandom rng = new SecureRandom();

/* Prints a random signed 32-bit integer. */ System.out.println(rng.nextInt()); } }</lang>

NetRexx

Works with: Mac OS X

and probably other UNIX systems that provide /dev/random or /dev/urandom random data source devices.

<lang NetRexx>/* NetRexx */ options replace format comments java crossref savelog symbols binary

import java.math.BigInteger

randomDevNameFile = File randomDevNameList = ['/dev/random', '/dev/urandom'] -- list of random data source devices randomDevIStream = InputStream do

 loop dn = 0 to randomDevNameList.length - 1
   randomDevNameFile = File(randomDevNameList[dn])
   if randomDevNameFile.exists() then leave dn -- We're done! Use this device
   randomDevNameFile = null -- ensure we don't use a non-existant device
   end dn
 if randomDevNameFile == null then signal FileNotFoundException('Cannot locate a random data source device on this system')
 -- read 8 bytes from the random data source device, convert it into a BigInteger then display the result
 randomBytes = byte[8]
 randomDevIStream = BufferedInputStream(FileInputStream(randomDevNameFile))
 randomDevIStream.read(randomBytes, 0, randomBytes.length)
 randomDevIStream.close()
 randomNum = BigInteger(randomBytes)
 say Rexx(randomNum.longValue()).right(24) '0x'Rexx(Long.toHexString(randomNum.longValue())).right(16, 0)

catch ex = IOException

 ex.printStackTrace()

end return

/* To run the program in a loop 10 times from a bash shell prompt use: for ((i=0; i<10; ++i)); do java <program_name>; done # Shell loop to run the command 10 times

  • /

</lang> Output:

$ for ((i=0; i<10; ++i)); do java RRandomGen; done # Shell loop to run the command 10 times
    -3724652236619320966 0xcc4f60865c70f17a
    -8287324416757903696 0x8cfd8259e0b94eb0
    -2951181559250748016 0xd70b4c02052cfd90
     8171526404483923658 0x716717f863fd3eca
    -4285529734202916706 0xc486bd699676009e
     4783094698411310978 0x4260f74949dc3f82
     6972277496665184225 0x60c28171482d97e1
    -2382194670272317046 0xdef0be919c96f98a
     7952058769071853043 0x6e5b6351938ecdf3
    -1857830580859698636 0xe637a8ee0f000234
$

OCaml

OCaml's default integers are 31 bits on 32 bits architectures:

<lang ocaml>let input_rand_int ic =

 let i1 = int_of_char (input_char ic)
 and i2 = int_of_char (input_char ic)
 and i3 = int_of_char (input_char ic)
 and i4 = int_of_char (input_char ic) in
 i1 lor (i2 lsl 8) lor (i3 lsl 16) lor (i4 lsl 24)

let () =

 let ic = open_in "/dev/urandom" in
 let ri31 = input_rand_int ic in
 close_in ic;
 Printf.printf "%d\n" ri31;
</lang>

but if we really want 32 bits integers there is a module for this:

<lang ocaml>let input_rand_int32 ic =

 let i1 = Int32.of_int (int_of_char (input_char ic))
 and i2 = Int32.of_int (int_of_char (input_char ic))
 and i3 = Int32.of_int (int_of_char (input_char ic))
 and i4 = Int32.of_int (int_of_char (input_char ic)) in
 let i2 = Int32.shift_left i2 8
 and i3 = Int32.shift_left i3 16
 and i4 = Int32.shift_left i4 24 in
 Int32.logor i1 (Int32.logor i2 (Int32.logor i3 i4))

let () =

 let ic = open_in "/dev/urandom" in
 let ri32 = input_rand_int32 ic in
 close_in ic;
 Printf.printf "%ld\n" ri32;
</lang>

Pascal

This works with FreePascal on "unixoids": <lang pascal>program RandomNumberDevice; var

 byteFile: file of byte;
 randomByte: byte;

begin

 assign(byteFile, '/dev/urandom');
 reset (byteFile);
 read  (byteFile, randomByte);
 close (byteFile);
 writeln('The random byte is: ', randomByte);

end. </lang> Output:

>: ./RandomNumberDevice
The random byte is: 9
>: ./RandomNumberDevice
The random byte is: 237

Perl

<lang Perl>sub read_random {

       my $device = '/dev/urandom';
       open my $in, "<:raw", $device   # :raw because it's not unicode string
               or die "Can't open $device: $!";
       sysread $in, my $rand, 4 * shift;
       unpack('L*', $rand);

}

print "$_\n" for read_random(10);</lang> /dev/urandom is not necessarily good enough for cryptographic work, though.

Perl 6

A lazy list of random numbers: <lang perl6>my $UR = open("/dev/urandom", :bin) or die "Can't open /dev/urandom: $!"; my @random-spigot := gather loop { take $UR.read(1024).unpack("L*") }

.say for @random-spigot[^10];</lang>

Output:
1431009271
1702240522
670020272
588612037
1864913839
2155430433
1690056587
385405103
2366495746
692037942

PicoLisp

<lang PicoLisp>: (in "/dev/urandom" (rd 4)) -> 2917110327</lang>

ProDOS

Uses math module: <lang ProDOS>printline -random- </lang>

PureBasic

PureBasic has the source for the random data is the "/dev/urandom" device on Linux or Mac OSX and the "Microsoft Cryptography API" on Windows. <lang PureBasic>If OpenCryptRandom()

 MyRandom = CryptRandom(#MAXLONG)
 CloseCryptRandom()

EndIf</lang>

Python

<lang Python>import random rand = random.SystemRandom() rand.randint(1,10)</lang>

Ruby

Ruby 1.8.7 introduces the 'securerandom' library. For MRI users, this library tries to get random numbers by loading OpenSSL, or opening /dev/urandom, or calling CryptGenRandom.

Works with: Ruby version 1.8.7

<lang Ruby>require 'securerandom' SecureRandom.random_number(1 << 32)</lang>

Tcl

<lang tcl>package require Tcl 8.5

  1. Allow override of device name

proc systemRandomInteger Template:Device "/dev/random" {

   set f [open $device "rb"]
   binary scan [read $f 4] "I" x
   close $f
   return $x

}</lang> Usage: <lang tcl>% puts [systemRandomInteger] 636131349</lang>

XPL0

The random number generator is seeded with the 32-bit system timer each time a program starts. From then on, a linear congruential algorithm is used (that passes the Diehard test suite). Since the Ran intrinsic routine returns a signed positive integer (modulo the argument), the value is limited to 31 bits.

<lang XPL0>code Ran=1; int R; R:= Ran($7FFF_FFFF)</lang>