Random number generator (device)

From Rosetta Code
Task
Random number generator (device)
You are encouraged to solve this task according to the task description, using any language you may know.
Task

If your system has a means to generate random numbers involving not only a software algorithm   (like the /dev/urandom devices in Unix),   then:

show how to obtain a random 32-bit number from that mechanism.

Ada[edit]

random.adb:

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;

BBC BASIC[edit]

Requires Windows XP or later.

      SYS "SystemFunction036", ^random%, 4
PRINT ~random%

C[edit]

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

#include <stdio.h>
#include <stdlib.h>
 
#define RANDOM_PATH "/dev/urandom"
 
int main(void)
{
unsigned char buf[4];
unsigned long v;
FILE *fin;
 
if ((fin = fopen(RANDOM_PATH, "r")) == NULL) {
fprintf(stderr, "%s: unable to open file\n", RANDOM_PATH);
return EXIT_FAILURE;
}
if (fread(buf, 1, sizeof buf, fin) != sizeof buf) {
fprintf(stderr, "%s: not enough bytes (expected %u)\n",
RANDOM_PATH, (unsigned) sizeof buf);
return EXIT_FAILURE;
}
fclose(fin);
v = buf[0] | buf[1] << 8UL | buf[2] << 16UL | buf[3] << 24UL;
printf("%lu\n", v);
return 0;
}

Library: BSD libc
[edit]

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.)

#include <inttypes.h> /* PRIu32 */
#include <stdlib.h> /* arc4random */
#include <stdio.h> /* printf */
 
int
main()
{
printf("%" PRIu32 "\n", arc4random());
return 0;
}

Library: OpenSSL
[edit]

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.

#include <inttypes.h>
#include <stdio.h>
 
#include <openssl/err.h>
#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;
}

Windows[edit]

Works with: MinGW
#include <stdio.h>  /* printf */
#include <windows.h>
#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;
}

C++[edit]

std::random_device is a uniformly-distributed integer random number generator that produces non-deterministic random numbers.

Note that std::random_device may be implemented in terms of a pseudo-random number engine if a non-deterministic source (e.g. a hardware device) is not available to the implementation.

See the C++ section on Random number generator (included) for the list of pseudo-random number engines available.

Works with: C++11
#include <iostream>
#include <random>
 
int main()
{
std::random_device rd;
std::uniform_int_distribution<long> dist; // long is guaranteed to be 32 bits
 
std::cout << "Random Number: " << dist(rd) << std::endl;
}

C#[edit]

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;
}

Park-Miller random number generator

 
const long m = 2147483647L;
const long a = 48271L;
const long q = 44488L;
const long r = 3399L;
static long r_seed = 12345678L;
 
public static byte gen()
{
long hi = r_seed / q;
long lo = r_seed - q * hi;
long t = a * lo - r * hi;
if (t > 0)
r_seed = t;
else
r_seed = t + m;
return (byte)r_seed;
}
 
public static void ParkMiller(byte[] arr)
{
byte[] arr = new byte[10900000];
for (int i = 0; i < arr.Length; i++)
{
arr[i] = gen();
}
}

ChucK[edit]

 Math.random2(-(Math.random()),Math.random(); 

EchoLisp[edit]

No random device provided by the host (browser). But we can use the system timer to get a physical input.

 
(random-seed "simon")
(random (expt 2 32))2275215386
(random-seed "simon")
(random (expt 2 32))2275215386 ;; the same
 
 
(random-seed (current-time-milliseconds ))
(random (expt 2 32))4061857345
(random-seed (current-time-milliseconds ))
(random (expt 2 32))1322611152
 


Forth[edit]

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 ;

Fortran[edit]

Using system /dev/urandom in GNU/Linux.

 
!-----------------------------------------------------------------------
! Test Linux urandom in Fortran
!-----------------------------------------------------------------------
program urandom_test
use iso_c_binding, only : c_long
implicit none
 
character(len=*), parameter :: RANDOM_PATH = "/dev/urandom"
integer :: funit, ios
integer(c_long) :: buf
 
open(newunit=funit, file=RANDOM_PATH, access="stream", form="UNFORMATTED", &
iostat=ios, status="old", action="read")
if ( ios /= 0 ) stop "Error opening file: "//RANDOM_PATH
 
read(funit) buf
 
close(funit)
 
write(*,'(A,I64)') "Integer: ", buf
write(*,'(A,B64)') "Binary: ", buf
write(*,'(A,Z64)') "Hexadecimal: ", buf
 
end program urandom_test
 

Go[edit]

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.

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()
}

Groovy[edit]

Based, necessarily, on Java solution:

def rng = new java.security.SecureRandom()

Test:

(0..4).each { println rng.nextInt() }
Output:
380425053
-1003791794
-1972330603
1152610574
714616658

Icon and Unicon[edit]

The following is Unicon-specific but trivially converted into Icon.

procedure main(A)
n := integer(A[1])|5
every !n do write(rand(4))
end
 
procedure rand(n)
f := open("/dev/urandom") | stop("Cannot get to urandom!")
x := 0
every !n do x := x*256 + ord(reads(f,1))
close(f)
return x
end

Sample runs:

->urand
910795827
1135996175
3545606085
944909079
2464790129
->

J[edit]

Untested:

256#.a.i.1!:11'/dev/urandom';0 4

Fallback:

256#.a.i.4{.host'dd if=/dev/urandom bs=4 count=1'

Note: this assumes that J is running on linux.

Java[edit]

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());
}
}

Julia[edit]

Works with: Linux
 
const rdev = "/dev/random"
rstream = try
open(rdev, "r")
catch
false
end
 
if isa(rstream, IOStream)
b = readbytes(rstream, 4)
close(rstream)
i = reinterpret(Int32, b)[1]
println("A hardware random number is: ", i)
else
println("The hardware random number stream, ", rdev, ", was unavailable.")
end
 
Output:
A hardware random number is:  986109744

Haskell[edit]

Library: Entropy
Works with: GHC version 7.4.1
#!/usr/bin/env runhaskell
 
import System.Entropy
import Data.Binary.Get
import qualified Data.ByteString.Lazy as B
 
main = do
bytes <- getEntropy 4
print (runGet getWord32be $ B.fromChunks [bytes])

Lasso[edit]

file(`/dev/urandom`)->readSomeBytes(4)->export32bits
Output:
723217350

Mathematica[edit]

rand32[] := RandomInteger[{-2^31, 2^31 - 1}]

Example: create array of 10 rand32 numbers

Table[rand32[], {i, 1, 10}]
Output:
{355587317, -869860319, -91421859, 1605907693, 101463390, 891823090, 
-531713717, -1038608428, 1717313407, 674189312}

NetRexx[edit]

Works with: Mac OS X
and probably other UNIX systems that provide /dev/random or /dev/urandom random data source devices.
/* 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
*/

 
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
$

Nim[edit]

var f = open("/dev/urandom")
var r: int32
discard f.readBuffer(addr r, 4)
close(f)
echo r

OCaml[edit]

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

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;
;;

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

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;
;;

PARI/GP[edit]

It works on systems having /dev/urandom and Linux.

rnd(n=10)=extern("cat /dev/urandom|tr -dc '[:digit:]'|fold -w"n"|head -1")

The code above creates a new function rnd() which returns cryptographically strong integers with max. 10 random digits from /dev/urandom. rnd(n) returns integer with max. n random digits. No leading zeros.

Output:
rnd() = 3055652197
rnd(20) = 75735303746547944580
... 

Pascal[edit]

This works with FreePascal on "unixoids":

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.
 
Output:
>: ./RandomNumberDevice
The random byte is: 9
>: ./RandomNumberDevice
The random byte is: 237

Perl[edit]

Typically one would use a module as they will work on UNIX, Win32, and other O/S's. Crypt::Random::Seed, for instance, will use Win32 sources, EGD/PRNGD, /dev/u?random, or if none of those exist for some reason, a userspace entropy method.

use Crypt::Random::Seed;
my $source = Crypt::Random::Seed->new( NonBlocking => 1 ); # Allow non-blocking sources like /dev/urandom
print "$_\n" for $source->random_values(10); # A method returning an array of 32-bit values

or (similar but many more dependencies):

use Crypt::Random::Source qw/get_weak/;    # Alternately get_strong
print unpack('L*',get_weak(4)), "\n" for 1..10;

Or we can read values from /dev/urandom ourselves:

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);

Whether /dev/urandom is good enough for cryptographic work is debated, though on most UNIX systems it is at least as good as the Win32 Crypto API.

Perl 6[edit]

A lazy list of random numbers:

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];
Output:
1431009271
1702240522
670020272
588612037
1864913839
2155430433
1690056587
385405103
2366495746
692037942

PicoLisp[edit]

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

ProDOS[edit]

Uses math module:

printline -random- 

PureBasic[edit]

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.

If OpenCryptRandom()
MyRandom = CryptRandom(#MAXLONG)
CloseCryptRandom()
EndIf

Python[edit]

import random
rand = random.SystemRandom()
rand.randint(1,10)

Racket[edit]

 
#lang racket
;; Assuming a device to provide random bits:
(call-with-input-file* "/dev/random"
(λ(i) (integer-bytes->integer (read-bytes 4 i) #f)))
 

REXX[edit]

version 1[edit]

/*REXX program generates a random  32-bit  number using the  RANDOM bif.*/
/*───────── The 32-bit random number is unsigned and constructed from */
/*───────── two smaller 16-bit numbers, and it's expressed in decimal.*/
/*───────── Note: the REXX random bif has a maximum range of 100,000.*/
 
numeric digits 10 /*ensure REXX has enough room. */
_=2**16 /*a handy-dandy constant to have.*/
 
say random(0,_-1)*_+random(0,_-1) /*gen an unsigned 32-bit random #*/
Output:
4294967296

version 2[edit]

This program generates a random 4 byte character string in the range '00000000'x to 'ffffffff'x

left=0
rite=0
lo=hex(left)hex(rite)
Say 'low ' c2x(lo)
left=random(0,2**16-1)
rite=random(0,2**16-1)
rand=hex(left)hex(rite)
Say 'random' c2x(rand)
left=2**16-1
rite=2**16-1
hi=hex(left)hex(rite)
Say 'high ' c2x(hi)
Exit
hex: Return d2c(arg(1),2)
Output:
low    00000000
random 3E4C3CDE
high   FFFFFFFF

Ring[edit]

 
nr = 10
for i = 1 to nr
see random(i) + nl
next
 

Ruby[edit]

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
require 'securerandom'
SecureRandom.random_number(1 << 32)

Sidef[edit]

func urandom() {
const device = %f'/dev/urandom';
 
device.open('<:raw', \var fh, \var err) ->
|| die "Can't open `#{device}': #{err}";
 
fh.sysread(\var noise, 4);
'L'.unpack(noise);
}
 
say urandom(); # sample: 3517432564

Tcl[edit]

package require Tcl 8.5
 
# Allow override of device name
proc systemRandomInteger {{device "/dev/random"}} {
set f [open $device "rb"]
binary scan [read $f 4] "I" x
close $f
return $x
}

Usage:

% puts [systemRandomInteger]
636131349

UNIX Shell[edit]

od -An -N 4 -t u4 /dev/urandom

XPL0[edit]

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.

code Ran=1;
int R;
R:= Ran($7FFF_FFFF)

zkl[edit]

Translation of: C

Linux:

const RANDOM_PATH="/dev/urandom";
 
fin,buf:=File(RANDOM_PATH,"r"), fin.read(4);
fin.close(); // GC would also close the file
println(buf.toBigEndian(0,4)); // 4 bytes @ offset 0
Output:
2152746403