## RNG147

### March 28, 2017

We have looked at random number generators in several previous exercises, but most of them returned integers. In today’s exercise we look at a simple random number generator that returns floating-point numbers. The generator is simple: Given a seed between zero and one, the next number in the sequence is the fractional portion of 147 times the seed.

Your task is to implement the random number generator described above, and to assess its suitability. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

Pages: 1 2

### 4 Responses to “RNG147”

1. Rutger said

In python 3

```def rng147(seed):
while True:
yield seed
seed = (147.0 * seed) % 1.0

r = rng147(0.1234)

for v in range(10):
print(next(r))
```
2. Graham said

Your sine trick only moves the problem elsewhere; try seeding with pi/6 (arcsin of 1/2).

Solution in Haskell, using the Stream package for explicitly infinite lists:

```module Main where

import           Data.Fixed  (mod')
import           Data.Stream (Stream)
import qualified Data.Stream as S

rng147 :: Double -> Stream Double
rng147 = S.iterate (\x -> (147 * x) `mod'` 1)

main :: IO ()
main = mapM_ print . S.take 10 . rng147 \$ pi / 10
```
3. Globules said

Here’s another Haskell version. With an integer argument, n, it prints the first n random numbers. With no arguments it converts the stream of random Doubles into a stream of 32-bit unsigned integers. The purpose is to feed that binary data to the dieharder program, which evaluates its randomness. We don’t make use of all the bits in the Double; it’s just an easy way of getting the data to dieharder in a form that it likes.

```{-# LANGUAGE ScopedTypeVariables #-}

import Data.Word (Word32)
import Foreign.Marshal.Alloc (alloca)
import Foreign.Storable (poke, sizeOf)
import System.Environment (getArgs)
import System.IO (hPutBuf, stdout)

-- A stream of "random" numbers.  (We take the tail to exclude the seed from the
-- values.)
rng147 :: RealFrac b => b -> [b]
rng147 = tail . iterate step
where step x = let (_ :: Int, f) = properFraction (147 * x) in f

main :: IO ()
main = do
let rs = rng147 (0.1234567 :: Double)
ns <- fmap (map read) getArgs :: IO [Int]
case ns of
-- Output an endless stream of 32-bit binary data for dieharder.
[]  -> put \$ map cvt rs

-- Print the first n random values.
[n] -> mapM_ print \$ take n rs

-- Invalid argument(s).
_   -> putStrLn "Usage: rng147 [n]"

-- Convert a value to an 32-bit unsigned integer, possibly throwing away the
-- least significant bits of the argument.
cvt :: RealFrac a => a -> Word32
cvt x = round \$ fromIntegral (maxBound :: Word32) * x

-- Output the unsigned 32-bit values as binary data.
put :: [Word32] -> IO ()
put is = let n = sizeOf (0 :: Word32)
in alloca (\p -> void (mapM_ (\i -> poke p i >> hPutBuf stdout p n) is))
```
```\$ ./rng147 10
0.14813489999999874
0.7758302999998143
4.705409997271204e-2
0.9169526959886696
0.7920463103344275
0.430807619160845
0.3287200166442119
0.32184244669915074
0.310839664775159
0.6934307219483742
```

Here’s the result of feeding the output to dieharder. I won’t try to interpret the results, here. (The -a argument tells it to run all the tests it has; -g 200 says that stdin is a series of 32-bit unsigned integers.) The summary is that 82 tests passed, 27 failed and 5 were weak.

```\$ ./rng147 | dieharder -a -g 200
#=============================================================================#
#            dieharder version 3.31.1 Copyright 2003 Robert G. Brown          #
#=============================================================================#
rng_name    |rands/second|   Seed   |
stdin_input_raw|  1.01e+07  |2776686247|
#=============================================================================#
test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
diehard_birthdays|   0|       100|     100|0.64044752|  PASSED
diehard_operm5|   0|   1000000|     100|0.00000000|  FAILED
diehard_rank_32x32|   0|     40000|     100|0.45366134|  PASSED
diehard_rank_6x8|   0|    100000|     100|0.97658733|  PASSED
diehard_bitstream|   0|   2097152|     100|0.72508491|  PASSED
diehard_opso|   0|   2097152|     100|0.00000000|  FAILED
diehard_oqso|   0|   2097152|     100|0.00000000|  FAILED
diehard_dna|   0|   2097152|     100|0.00000000|  FAILED
diehard_count_1s_str|   0|    256000|     100|0.00000000|  FAILED
diehard_count_1s_byt|   0|    256000|     100|0.00000000|  FAILED
diehard_parking_lot|   0|     12000|     100|0.00000000|  FAILED
diehard_2dsphere|   2|      8000|     100|0.00000000|  FAILED
diehard_3dsphere|   3|      4000|     100|0.00000000|  FAILED
diehard_squeeze|   0|    100000|     100|0.00000000|  FAILED
diehard_sums|   0|       100|     100|0.06709806|  PASSED
diehard_runs|   0|    100000|     100|0.00000000|  FAILED
diehard_runs|   0|    100000|     100|0.00000000|  FAILED
diehard_craps|   0|    200000|     100|0.13428702|  PASSED
diehard_craps|   0|    200000|     100|0.00096831|   WEAK
marsaglia_tsang_gcd|   0|  10000000|     100|0.00000000|  FAILED
marsaglia_tsang_gcd|   0|  10000000|     100|0.00000000|  FAILED
sts_monobit|   1|    100000|     100|0.03994929|  PASSED
sts_runs|   2|    100000|     100|0.22979976|  PASSED
sts_serial|   1|    100000|     100|0.98471576|  PASSED
sts_serial|   2|    100000|     100|0.31624292|  PASSED
sts_serial|   3|    100000|     100|0.13274265|  PASSED
sts_serial|   3|    100000|     100|0.06274970|  PASSED
sts_serial|   4|    100000|     100|0.10906298|  PASSED
sts_serial|   4|    100000|     100|0.71359846|  PASSED
sts_serial|   5|    100000|     100|0.00790811|  PASSED
sts_serial|   5|    100000|     100|0.07231695|  PASSED
sts_serial|   6|    100000|     100|0.17659272|  PASSED
sts_serial|   6|    100000|     100|0.18513720|  PASSED
sts_serial|   7|    100000|     100|0.04315090|  PASSED
sts_serial|   7|    100000|     100|0.45634930|  PASSED
sts_serial|   8|    100000|     100|0.14826946|  PASSED
sts_serial|   8|    100000|     100|0.42520026|  PASSED
sts_serial|   9|    100000|     100|0.71305937|  PASSED
sts_serial|   9|    100000|     100|0.20822407|  PASSED
sts_serial|  10|    100000|     100|0.97154428|  PASSED
sts_serial|  10|    100000|     100|0.69812982|  PASSED
sts_serial|  11|    100000|     100|0.53454147|  PASSED
sts_serial|  11|    100000|     100|0.08444014|  PASSED
sts_serial|  12|    100000|     100|0.22453592|  PASSED
sts_serial|  12|    100000|     100|0.72236320|  PASSED
sts_serial|  13|    100000|     100|0.78366045|  PASSED
sts_serial|  13|    100000|     100|0.37616667|  PASSED
sts_serial|  14|    100000|     100|0.95764809|  PASSED
sts_serial|  14|    100000|     100|0.14472891|  PASSED
sts_serial|  15|    100000|     100|0.43901688|  PASSED
sts_serial|  15|    100000|     100|0.76714556|  PASSED
sts_serial|  16|    100000|     100|0.58587727|  PASSED
sts_serial|  16|    100000|     100|0.67425978|  PASSED
rgb_bitdist|   1|    100000|     100|0.05846675|  PASSED
rgb_bitdist|   2|    100000|     100|0.00004623|   WEAK
rgb_bitdist|   3|    100000|     100|0.66589418|  PASSED
rgb_bitdist|   4|    100000|     100|0.00026565|   WEAK
rgb_bitdist|   5|    100000|     100|0.07969442|  PASSED
rgb_bitdist|   6|    100000|     100|0.17850326|  PASSED
rgb_bitdist|   7|    100000|     100|0.25911992|  PASSED
rgb_bitdist|   8|    100000|     100|0.00045592|   WEAK
rgb_bitdist|   9|    100000|     100|0.00642740|  PASSED
rgb_bitdist|  10|    100000|     100|0.27514527|  PASSED
rgb_bitdist|  11|    100000|     100|0.91420132|  PASSED
rgb_bitdist|  12|    100000|     100|0.09738292|  PASSED
rgb_minimum_distance|   2|     10000|    1000|0.00000000|  FAILED
rgb_minimum_distance|   3|     10000|    1000|0.00000000|  FAILED
rgb_minimum_distance|   4|     10000|    1000|0.00000000|  FAILED
rgb_minimum_distance|   5|     10000|    1000|0.01232138|  PASSED
rgb_permutations|   2|    100000|     100|0.55323173|  PASSED
rgb_permutations|   3|    100000|     100|0.00000000|  FAILED
rgb_permutations|   4|    100000|     100|0.00000000|  FAILED
rgb_permutations|   5|    100000|     100|0.00000000|  FAILED
rgb_lagged_sum|   0|   1000000|     100|0.76792249|  PASSED
rgb_lagged_sum|   1|   1000000|     100|0.59838659|  PASSED
rgb_lagged_sum|   2|   1000000|     100|0.95607401|  PASSED
rgb_lagged_sum|   3|   1000000|     100|0.28565715|  PASSED
rgb_lagged_sum|   4|   1000000|     100|0.95085961|  PASSED
rgb_lagged_sum|   5|   1000000|     100|0.45582064|  PASSED
rgb_lagged_sum|   6|   1000000|     100|0.60565985|  PASSED
rgb_lagged_sum|   7|   1000000|     100|0.04195406|  PASSED
rgb_lagged_sum|   8|   1000000|     100|0.30831976|  PASSED
rgb_lagged_sum|   9|   1000000|     100|0.36546234|  PASSED
rgb_lagged_sum|  10|   1000000|     100|0.19936994|  PASSED
rgb_lagged_sum|  11|   1000000|     100|0.07303233|  PASSED
rgb_lagged_sum|  12|   1000000|     100|0.34645127|  PASSED
rgb_lagged_sum|  13|   1000000|     100|0.29195838|  PASSED
rgb_lagged_sum|  14|   1000000|     100|0.30094975|  PASSED
rgb_lagged_sum|  15|   1000000|     100|0.99790005|   WEAK
rgb_lagged_sum|  16|   1000000|     100|0.75196523|  PASSED
rgb_lagged_sum|  17|   1000000|     100|0.38809626|  PASSED
rgb_lagged_sum|  18|   1000000|     100|0.61180091|  PASSED
rgb_lagged_sum|  19|   1000000|     100|0.19440479|  PASSED
rgb_lagged_sum|  20|   1000000|     100|0.57917094|  PASSED
rgb_lagged_sum|  21|   1000000|     100|0.83129601|  PASSED
rgb_lagged_sum|  22|   1000000|     100|0.57292407|  PASSED
rgb_lagged_sum|  23|   1000000|     100|0.10381929|  PASSED
rgb_lagged_sum|  24|   1000000|     100|0.93651195|  PASSED
rgb_lagged_sum|  25|   1000000|     100|0.50848729|  PASSED
rgb_lagged_sum|  26|   1000000|     100|0.81756629|  PASSED
rgb_lagged_sum|  27|   1000000|     100|0.29194323|  PASSED
rgb_lagged_sum|  28|   1000000|     100|0.14934239|  PASSED
rgb_lagged_sum|  29|   1000000|     100|0.96722837|  PASSED
rgb_lagged_sum|  30|   1000000|     100|0.41045537|  PASSED
rgb_lagged_sum|  31|   1000000|     100|0.33379469|  PASSED
rgb_lagged_sum|  32|   1000000|     100|0.67528985|  PASSED
rgb_kstest_test|   0|     10000|    1000|0.12422629|  PASSED
dab_bytedistrib|   0|  51200000|       1|1.00000000|  FAILED
dab_dct| 256|     50000|       1|0.00000000|  FAILED
Preparing to run test 207.  ntuple = 0
dab_filltree|  32|  15000000|       1|0.00000000|  FAILED
dab_filltree|  32|  15000000|       1|0.00000000|  FAILED
Preparing to run test 208.  ntuple = 0
dab_filltree2|   0|   5000000|       1|0.00000000|  FAILED
dab_filltree2|   1|   5000000|       1|0.00000000|  FAILED
Preparing to run test 209.  ntuple = 0
dab_monobit2|  12|  65000000|       1|1.00000000|  FAILED
\$
```
4. […] built several random number generators: [1], [2], [3], [4], [5], [6], [7], [8], [9] (I didn’t realize it was so many until I went back and looked). In today’s exercise we […]