? and ?. Improved |
initial writing: 2003-10-11 last updated: 2005-03-15 |
? (and ?.) have been improved in the following ways:
1. A New Random Number Generator
? (and ?.) now use the GB_FLIP random number generator in Donald Knuth’s GraphBase library. GB_FLIP, a subtractive method, replaces the linear congruential method developed by D.H. Lehmer in 1951. It is better in the following ways:
As before, the foreigns 9!:0 and 9!:1 inquire and set the random number seed. However, now the seed is unchanged by using ? (or ?.). That is, the result of 9!:0 is the value of the seed the last time it was set by 9!:1 .
Random numbers generated using the old method are available through the verbs roll and deal in section 4 below.
2. Uniform 0-1 Random Numbers
?0 , previously a domain error, has been changed to produce a random floating point number from the uniform distribution [0,1) (greater than or equal to 0 and less than 1). Thus to generate one million such numbers one could say ?1e6$0 or, more efficiently (by exploiting special code), 1e6 ?@$ 0 .
? 2 5$0 0.228966 0.322778 0.83538 0.527181 0.994417 0.586394 0.80113 0.545236 0.0584635 0.427982 ? 0 10 20 0.257946 9 5
Random 0-1 numbers can be generated nearly as efficiently as -- within a factor of 2 -- random integers, as the following benchmarks demonstrate:
ts=: 6!:2 , 7!:2@] NB. time and space ts '+/i.1e6' NB. calibration 0.0400596 4.19546e6 ts '?1e6$0' NB. random floats 0.127696 9.43795e6 ts '1e6 ?@$ 0' NB. special code 0.114351 8.38944e6 ts '?1e6$2e9' NB. random integers 0.164644 8.38931e6 ts '1e6 ?@$ 2e9' NB. special code 0.0680324 4.19526e6
The resolution of random floating point numbers so generated depends on the underlying hardware; the resolution is one part in 2^53 on the PC with 64-bit IEEE floating point numbers. The generation of these numbers can be modelled thus:
U=: 3 : '(2^53) %~ (2^30) #. ?(y.,2)$2^23 30' U 2 5 0.627997 0.254797 0.339676 0.995029 0.617055 0.641366 0.212932 0.958605 0.75816 0.229028 2 ^. +./ 1e6 ?@$ 0 _53
3. Special Code
The following dyads are now supported by special code:
? @$ | ? @:$ | [: ? $ | |||
?.@$ | ?.@:$ | [: ?. $ | |||
? @# | ? @:# | [: ? # | |||
?.@# | ?.@:# | [: ?. # |
b=: 1e6$2 i=: 1e6$1e7 ts=: 6!:2 , 7!:2@] NB. time and space ts 'Expression'
Expression | J 5.03 | J 5.02 | Ratio | |||||||||
?b | 0.015900 | 1049152 | 0.323943 | 5243520 | 20.37 | 5.00 | ||||||
?i | 0.144913 | 4194880 | 0.667152 | 4194944 | 4.60 | 1.00 | ||||||
?1e6$2 | 0.045027 | 5243520 | 0.347825 | 9437888 | 7.72 | 1.80 | ||||||
?1e6$1e7 | 0.170378 | 8389312 | 0.692795 | 8389376 | 4.07 | 1.00 | ||||||
1e6 ?@$ 2 | 0.006729 | 1049344 | 0.352622 | 9438016 | 52.41 | 8.99 | ||||||
1e6 ?@$ 1e7 | 0.074965 | 4195264 | 0.691673 | 8389632 | 9.23 | 2.00 |
4. Model of Roll and Deal
Random numbers generated using the old linear congruential method are available through the verbs roll and deal , from P.C. Berry, Sharp APL Reference Manual, 1979. bigdeal is by E.E. McDonnell circa 1966, for small x and large y .
qrl =: 7^5 NB. initial random seed value tick =: [ <.@%~ (* 3 : 'qrl=:(<:2^31)|(7^5)*qrl')@] roll =: (<:2^31)&tick"0 rix =: i.@[ ([ ,. [ + roll@:-~) ] deal1=: [ {. <@~."1@|.@rix C. i.@-@] deal =: deal1 ` bigdeal @. (< 0.01&*) " 0 bigdeal=: 4 : 0 t=. 0 $ v=. y. $~ <.1.11*x. while. x. > #t do. t=. ~. roll v end. x. {. t ) test=: 3 : 0 NB. run this in pre J 5.03 version 9!:1 ] qrl=: 7^5 assert. (? -: roll) 100$1e6 assert. (? -: roll) 100$2 assert. qrl -: 9!:0 '' assert. 100 (? -: deal) 100 assert. 100 (? -: deal) 1000 assert. 100 (? -: deal) 10000 assert. 100 (? -: deal) 10001 assert. qrl -: 9!:0 '' 1 ) roll 10$100 13 75 45 53 21 4 67 67 93 38 0j0 ": qrl 823564440 10 deal 100 48 16 94 91 45 31 93 57 85 53 0j0 ": qrl 896544303