Random number generator (device): Difference between revisions
Fortran 2008 version with urandom |
|||
Line 117: | Line 117: | ||
== {{header|ChucK}} == |
== {{header|ChucK}} == |
||
<lang> Math.random2(-(Math.random()),Math.random(); </lang> |
<lang c> Math.random2(-(Math.random()),Math.random(); </lang> |
||
== {{header|C++}} == |
== {{header|C++}} == |
Revision as of 13:35, 14 February 2015
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 <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;
}</lang>
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 */
- include <stdlib.h> /* arc4random */
- include <stdio.h> /* printf */
int main() {
printf("%" PRIu32 "\n", arc4random()); return 0;
}</lang>
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>
- 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;
}</lang>
Windows
<lang c>#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;
}</lang>
ChucK
<lang c> Math.random2(-(Math.random()),Math.random(); </lang>
C++
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.
<lang cpp>#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;
}</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>
Fortran
Using system /dev/urandom in GNU/Linux.
<lang fortran> !----------------------------------------------------------------------- ! 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 </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
Icon and Unicon
The following is Unicon-specific but trivially converted into Icon.
<lang unicon>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</lang>
Sample runs:
->urand 910795827 1135996175 3545606085 944909079 2464790129 ->
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>
Haskell
<lang haskell>#!/usr/bin/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])</lang>
Lasso
<lang lasso>file(`/dev/urandom`)->readSomeBytes(4)->export32bits</lang>
- Output:
723217350
Mathematica
<lang Mathematica>rand32[] := RandomInteger[{-2^31, 2^31 - 1}]</lang>
Example: create array of 10 rand32 numbers <lang Mathematica>Table[rand32[], {i, 1, 10}]</lang>
- Output:
{355587317, -869860319, -91421859, 1605907693, 101463390, 891823090, -531713717, -1038608428, 1717313407, 674189312}
NetRexx
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 $
Nim
<lang nim>var f = open("/dev/urandom") var r: int32 discard f.readBuffer(addr r, 4) close(f) echo r</lang>
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
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. <lang Perl>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</lang> or (similar but many more dependencies): <lang Perl>use Crypt::Random::Source qw/get_weak/; # Alternately get_strong print unpack('L*',get_weak(4)), "\n" for 1..10;</lang>
Or we can read values from /dev/urandom ourselves: <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> 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
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>
Racket
<lang Racket>
- lang racket
- Assuming a device to provide random bits
(call-with-input-file* "/dev/random"
(λ(i) (integer-bytes->integer (read-bytes 4 i) #f)))
</lang>
REXX
<lang rexx>/*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 #*/</lang>
- Output:
4294967296
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.
<lang Ruby>require 'securerandom' SecureRandom.random_number(1 << 32)</lang>
Tcl
<lang tcl>package require Tcl 8.5
- 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>
UNIX Shell
<lang UNIX Shell>od -An -N 4 -t u4 /dev/urandom</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>